Android--根据子控件的大小自动换行的ViewGroup
1、自定义ViewGroup
/**
* Created by Administrator on 2016/2/26.
*
* --------自动换行的ViewGroup-----------
*/
public class LineWrapLayout extends ViewGroup {
private static final boolean DEBUG = true;
private static final String TAG = "AutoLineFeedLayout"; /**
* 左间距
*/
private int paddingLeft = 10;
/**
* 右间距
*/
private int paddingRight = 10;
/**
*
*/
private int paddingTop = 10;
/**
*
*/
private int paddingBottom = 10; /**
* 水平方向间距
*/
private int horizontalSpace = 10;
/**
* 行间距
*/
private int verticalSpace = 5; private List<Integer> listX;
private List<Integer> listY; public LineWrapLayout(Context context) {
super(context); }
public LineWrapLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
} public LineWrapLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(DEBUG) Log.d(TAG, "--- onLayout changed :" + changed + " l :" + l + ",t :" + t + ",r :" + r + ",b :" + b);
int count = getChildCount();
int width = getWidth();
Log.i(TAG, "宽度 :"+width); int startOffsetX = paddingLeft;// 横坐标开始
int startOffsety = 0;//纵坐标开始
int rowCount = 1; int preEndOffsetX = startOffsetX; for (int i = 0; i < count; i++) {
final View childView = getChildAt(i); int w = childView.getMeasuredWidth();
int h = childView.getMeasuredHeight(); int x = listX.get(i);
int y = listY.get(i); // 布局子控件
childView.layout(x, y, x + w, y + h);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(DEBUG) Log.v(TAG, "--- onMeasure()"); int count = getChildCount();
int width = measureWidth(widthMeasureSpec);
Log.i(TAG, "宽度 :"+width); int startOffsetX = paddingLeft;// 横坐标开始
int startOffsety = 0+paddingTop;//纵坐标开始
int rowCount = 1; int preEndOffsetX = startOffsetX; listX.clear();
listY.clear();
for (int i = 0; i < count; i++) {
Log.v(TAG, "----");
final View childView = getChildAt(i);
// 设置子空间Child的宽高
childView.measure(0,0);
/* 获取子控件Child的宽高 */
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
Log.v(TAG, "childWidth :"+childWidth+" childHeight :"+childHeight);
preEndOffsetX = startOffsetX + childWidth /*+ CHILD_MARGIN*/;
//TODO [yaojian]margin属性?
if (preEndOffsetX > width - paddingRight ) {
if (startOffsetX > paddingLeft) {
/* 换行 */
startOffsetX = paddingLeft;
startOffsety += childHeight+verticalSpace;
rowCount++;
}
}
Log.d(TAG, "measure child :"+startOffsetX+", "+startOffsety+", "+preEndOffsetX+", "+(startOffsety+childHeight));
listX.add(startOffsetX);
listY.add(startOffsety); // childView.layout(startOffsetX, startOffsety, preEndOffsetX, startOffsety+childHeight);
startOffsetX = startOffsetX + childWidth + horizontalSpace;
}
int lastLineHeight = 0;
View lastChild = getChildAt(count-1);
if(null != lastChild){
lastLineHeight = lastChild.getMeasuredHeight();
}
setMeasuredDimension(measureWidth(widthMeasureSpec), startOffsety+lastLineHeight+paddingBottom);
// super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 注意setMeasuredDimension和resolveSize的用法
// setMeasuredDimension(resolveSize(measuredWidth, widthMeasureSpec),
// resolveSize(top, heightMeasureSpec));
} private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); // Default size if no limits are specified.
int result = 400; if (specMode == MeasureSpec.AT_MOST) {
// Calculate the ideal size of your control
// within this maximum size.
// If your control fills the available space
// return the outer bound.
result = specSize;
} else if (specMode == MeasureSpec.EXACTLY) {
// If your control can fit within these bounds return that value.
result = specSize;
}
return result;
} private void init(AttributeSet attrs) {
TypedArray attrArray = getContext().obtainStyledAttributes(attrs, R.styleable.AutoLineFeedLayout);
int attrCount = attrArray.getIndexCount();
for (int i = 0; i < attrCount; i++) {
int attrId = attrArray.getIndex(i);
switch (attrId) {
case R.styleable.AutoLineFeedLayout_horizontalSpacing:{
float dimen = attrArray.getDimension(attrId, 0);
horizontalSpace = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_verticalSpacing:{
float dimen = attrArray.getDimension(attrId, 0);
verticalSpace = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_paddingBottom:{
float dimen = attrArray.getDimension(attrId, 0);
paddingBottom = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_paddingLeft:{
float dimen = attrArray.getDimension(attrId, 0);
paddingLeft = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_paddingRight:{
float dimen = attrArray.getDimension(attrId, 0);
paddingRight = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_paddingTop:{
float dimen = attrArray.getDimension(attrId, 0);
paddingTop = (int) dimen;
}
break;
case R.styleable.AutoLineFeedLayout_debug:{ }
break; default:
break;
} } listX = new ArrayList<Integer>();
listY = new ArrayList<Integer>();
}
}
2、有一部分自定义属性可供使用 attrs.xml
<declare-styleable name="AutoLineFeedLayout">
<attr name="debug" format="boolean"></attr> <attr name="paddingLeft" format="reference|dimension"/>
<attr name="paddingRight" format="reference|dimension"/>
<attr name="paddingTop" format="reference|dimension"/>
<attr name="paddingBottom" format="reference|dimension"/> <attr name="verticalSpacing" format="reference|dimension"/>
<attr name="horizontalSpacing" format="reference|dimension"/>
</declare-styleable>
3、在布局文件中和普通ViewGroup使用相同
4、在Activity中动态添加View或者ViewGroup
for (int i = 0;i < myData.getList().length;i++){
View child = View.inflate(ZhuanTiActivity.this,R.layout.item_mygridview_layout,null);
TextView textView = (TextView) child.findViewById(R.id.tv_title_item);
textView.setText(myData.getList()[i].getName());
textView.setTextColor(Color.argb(255, colorR, colorG, colorB));
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("aaa",textView.getText());
}
});
custom_index_zhuanTiActivity.addView(child);
}
Android--根据子控件的大小自动换行的ViewGroup的更多相关文章
- Android ScrollView 子控件不占满的问题
经常碰到很笨的 ScrollView的子控件无法占满 ScrollView 的空间的问题. 其实只需要加一行,android:fillViewport="true" 但不加上这行就 ...
- Android listview子控件的的点击事件(转)
1.先看图,是否是你想要的 2.布局文件<?xml version="1.0" encoding="utf-8"?><LinearLayout ...
- Android ListView 子控件点击事件
android:descendantFocusability beforeDescendants:viewgroup会优先其子类控件而获取到焦点 afterDescendants:viewgroup只 ...
- Android 布局之LinearLayout 子控件weight权重的作用详析(转)
关于Android开发中的LinearLayout子控件权重android:layout_weigh参数的作用,网上关于其用法有两种截然相反说法: 说法一:值越大,重要性越高,所占用的空间越大: 说法 ...
- Android 布局之LinearLayout 子控件weight权重的作用详析
关于Android开发中的LinearLayout子控件权重android:layout_weigh参数的作用,网上关于其用法有两种截然相反说法: 说法一:值越大,重要性越高,所占用的空间越大: 说法 ...
- [转]Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件
Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件. 1.为了防止拖动ListView时,在列表末尾重复数据显示.需要加入 HashMap<In ...
- Android中动态改变控件的大小的一种方法
在Android中有时候我们需要动态改变控件的大小.有几种办法可以实现 一是在onMeasure中修改尺寸,二是在onLayout中修改位置和尺寸.这个是可以进行位置修改的,onMeasure不行. ...
- 记录下帮助一位网友解决的关于android子控件的onTouch或onClick和父OnTouch 冲突的问题。
前三天收到位网友的私信求助,问题大概如标题所示.具体是下面的情况,个人感觉,这个问题挺有趣,也会在实际项目开发中很常见.不想看前奏的请直接跳至解决方法. 问题原型: 父控件是自定义的 LinearLa ...
- Android自定义组合控件内子控件无法显示问题
今天自定义了一个组合控件,与到了个奇葩问题: 我自定义了一个RelativeLayout,这个layout内有多个子控件.但奇怪的是这些子控件一直显示不出来.调试了一下午,竟然是因为在获取(infla ...
随机推荐
- ThreadLocal管理Connection
ThreadLocal管理Connection 每一个用户都对应有一个单独线程,每一个线程都有一个数据库连接对象Connection对象接待它. 一个用户对应一个线程,这个线程中的Connection ...
- Spring的JavaMail实现异步发送邮件
具体背景就不说了,可以网上搜索相关知识,或者直接看Sping MailSender的官坊网页.这里就直接实战了(Java实现异步发送电子邮件,包含中文无乱码). Maven: <dependen ...
- Spring Security 与 OAuth2 介绍
个人 OAuth2 全部文章 Spring Security 与 OAuth2(介绍):https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 ...
- 2016-06-14 发布 解决Centos7初次开机提示Initial setup of CentOS Linux 7 (core)
安装完成centos7后出现如下提示: Initial setup of CentOS Linux 7 (core) 1) [x] Creat user 2) [!] License informat ...
- java-构建jar带哟参数提示的
使用command的cli包构建带有参数提示的jar包 需要引入command cli的依赖 <commons.version>1.2</commons.version> &l ...
- Linux-(watch,at,crontab)
watch命令 1.命令格式: watch [参数] [命令] 2.命令功能: 可以将命令的输出结果输出到标准输出设备,多用于周期性执行命令/定时执行命令. watch可以帮你监测一个命令的运行结 ...
- WPF中的Visual Tree和Logical Tree与路由事件
1.Visual Tree和Logical TreeLogical Tree:逻辑树,WPF中用户界面有一个对象树构建而成,这棵树叫做逻辑树,元素的声明分层结构形成了所谓的逻辑树!!Visual Tr ...
- Executor简介
Executor是一个接口,这个接口负责执行提交给它的任务(Runnable对象).这个接口能够使“任务提交”与“任务执行”解耦.即某人只要把任务提交给Executor就好了,至于它怎么给任务 ...
- 纯css竟可以做出边框这样长宽度的过渡效果
边框效果如下:鼠标移到下面方形,就有效果 要是没有效果,点这个:https://murenziwei.github.io/testGit/Untitled1.html 正如你所看到的,这边框颜色只 ...
- 使用Docker调试Asp.Net Core
使用 Docker 进行部署 目前还是使用将发布出来的文件打包进docker镜像的形式 $ docker build -t pims . $ docker run --name pims --rm - ...