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 ...
随机推荐
- vs 2017 IIS EXPRESS 增加局域网访问
在VS调试站点,默认使用IISExpress,locall+端口,为了使用IP地址.多域名调试,找到 IISExpress下的applicationhost.config,在目标站点下增加类似行: & ...
- 插入排序的Java代码实现
插入排序也是一类非常常见的排序方法,它主要包含直接插入排序,Shell排序和折半插入排序等几种常见的排序方法. 1.直接插入排序 直接插入排序的思路非常简单:依次将待排序的数据元素按其关键字值的大小插 ...
- Centos7安装Nginx实战
一.背景 最近在写一些自己的项目,用到了nginx,所以自己动手来在Centos7上安装nginx,以下是安装步骤. 二.基本概念以及应用场景 1.什么是nginx Nginx是一款使用C语言开发的高 ...
- 什么是编程语言,什么是Python解释器
转自白月黑羽python在线教程:http://www.python3.vip/doc/blog/python/2018071401/ 0基础学Python之1:什么是编程语言,什么是Python解释 ...
- 自然语言处理--jieba和gensim的分词功能
一.jieba分词功能 1.主要模式 支持三种分词模式: 精确模式,试图将句子最精确地切开,适合文本分析: 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义: 搜索引擎模 ...
- java Queue的用法
https://www.cnblogs.com/caozengling/p/5307992.html https://blog.csdn.net/a724888/article/details/802 ...
- 「每日一码」(精品代码,质量保证)empty和undefined
将每天看到的优秀的代码或者特别的实现,记录下来 2019-2-26 empty和undefined 数组的filter,以下输出结果是什么 var arr = [1,2,3]; arr[10] = 9 ...
- postman参数化 接口响应数据获取符合条件的内容参数化给后面的接口使用
一:主要内容 从响应结果中找到满足条件的key,获取其value,参数化给后面的接口使用 二:参数化获取想要的value值,传给后面的接口使用 有时我们获取的响应数据,需要的那个字段可能在一个数组里面 ...
- Python多版本管理器-pyenv 介绍及部署记录
一. pyenv简单介绍 在日常运维中, 经常遇到这样的情况: 系统自带的Python是2.x,而业务部署需要Python 3.x 环境, 此时需要在系统中安装多个Python版本,但又不能影响系统自 ...
- set集合容器(常用的使用方法总结)
关于C++STL中set集合容器的学习,看别人的代码一百遍,不如自己动手写一遍. 构造set集合容器的目的是为了去重+排序+快速搜索.由于set集合容器实现了红黑树多的平衡二叉检索树的数据结构,在插 ...