一些带搜索功能的app,在搜索栏下面一般会提供一些关键字供用户选择。
也可以根据用户输入的文字,在下一次使用的时候该文字出现在常用关键字里面,只要轻轻一点就可以搜索了,无需再次输入。
关键字可以动态添加,这就要考虑换行的问题了
废话不多说,先上效果图:
先定义2个自定义属性
<declare-styleable name="linewarplayout">
<attr name="magin" format="integer" />
<attr name="itemBg" format="reference"></attr>
</declare-styleable>itemBg:关键字的背景
.......
算了不写了
上代码
package com.tang.linewraplayout;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class LineWrapLayout extends ViewGroup
{
private int magin = 20;//每个VIEW之间的间距
private List<List<View>> mAllChildViews = new ArrayList<List<View>>();//所有子控件
private List<Integer> mLineHeight =new ArrayList<Integer>();//每一行的高度
public interface OnItemClickListener//点击事件接口
{
public void onClick(View view);
}
private OnItemClickListener clickListener;
public void setOnItemClickListener(OnItemClickListener clickListener)
{
this.clickListener=clickListener;
}
private Context context;
private int bgId=0;//textview背景ID
public LineWrapLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
this.context = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.linewarplayout);
magin = a.getInt(R.styleable.linewarplayout_magin, 20);
bgId = a.getResourceId(R.styleable.linewarplayout_itemBg, R.drawable.text_bg);
}
/**
* 关键字数据
* @param data
*/
public void setData(List<String> data)
{
Log.i("AAA", "setData:"+data.size());
for(int i = 0;i<data.size();i++)
{
TextView textView = new TextView(context);
textView.setText(data.get(i));
if(bgId!=0)
textView.setBackgroundResource(bgId);
textView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
clickListener.onClick(v);
}
});
this.addView(textView);
}
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams()
{
return new MarginLayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//取得控件的宽高
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
//测量模式
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int mWidth = 0;
int mHeight = 0;
int lineWidth = 0;
int lineHeight = 0;
int mCount = getChildCount();
for (int i = 0; i < mCount; i++)
{
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
// 当前子控件占据的宽度和高度+子控件之间的间距
int childWidth = child.getMeasuredWidth() + magin +lp.leftMargin
+ lp.rightMargin;
int childHeight = child.getMeasuredHeight() + magin +lp.topMargin
+ lp.bottomMargin;
int temp = lineWidth + childWidth;
if (temp <= sizeWidth)
{
//当新加的子控件宽度+当前行所有子控件之和还小于父控件宽度
//说明当前行还可以添加
lineWidth += childWidth;
lineHeight = Math.max(lineHeight, childHeight);
}
else
{
//否则的话就要增加一行了
mWidth = Math.max(lineWidth, mWidth);// 取最大的
lineWidth = childWidth; // 重新开启新行,开始记录
// 加上当前高度,
mHeight += lineHeight;
// 开启记录下一行的高度
lineHeight = childHeight;
}
}
//加上最后一行的高度
mHeight += lineHeight;
mWidth = Math.max(mWidth, lineWidth);
mHeight =Math.max(mHeight, lineHeight);
setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth
: mWidth, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight
: mHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
mAllChildViews.clear();
mLineHeight.clear();
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
// 每一行所有的childView
List<View> lineViews = new ArrayList<View>();
int mCount = getChildCount();
Log.i("AAA", "mCount:"+mCount);
// 遍历所有
for (int i = 0; i < mCount; i++)
{
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int temp = childWidth + magin +lp.leftMargin+ lp.rightMargin + lineWidth;
// 如果不需要换行
if (temp <= width)
{
lineWidth = temp;
lineHeight = Math.max(lineHeight, childHeight + magin +lp.topMargin
+ lp.bottomMargin);
lineViews.add(child);
}
else
{
// 记录这一行的高度
mLineHeight.add(lineHeight);
// 将当前行的View保存,然后new 一个List保存下一行的child
mAllChildViews.add(lineViews);
lineViews = new ArrayList<View>();
lineViews.add(child);
lineHeight = childHeight + magin +lp.topMargin+ lp.bottomMargin;
lineWidth = childWidth + magin +lp.leftMargin+ lp.rightMargin;
}
}
// 将最后一行加入队列
mLineHeight.add(lineHeight);
mAllChildViews.add(lineViews);
int left = 0;
int top = 0;
// 总行数
int count = mAllChildViews.size();
for (int i = 0; i < count; i++)
{
lineViews = mAllChildViews.get(i);
lineHeight = mLineHeight.get(i);
// 遍历当前行所有的View
for (int j = 0; j < lineViews.size(); j++)
{
View child = lineViews.get(j);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int lc = left + magin+lp.leftMargin;
int tc = top + magin+lp.topMargin;
int rc =lc + child.getMeasuredWidth();
int bc = tc + child.getMeasuredHeight();
child.layout(lc, tc, rc, bc);
left += child.getMeasuredWidth() + lp.rightMargin+lp.leftMargin
+ magin;
}
left = 0;
top += lineHeight;
}
}
}
在onlayout中将子控件添加到指定的位置
使用setData将关键字数据集传递进来,生成子控件,添加点击事件
使用OnItemClickListener接口将子控件的点击事件传递出去
注意:若前者计算不正确的话子控件会漏掉一部分,显示不完全
使用:
<com.tang.linewraplayout.LineWrapLayout
android:id="@+id/linewarplayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1"
android:layout_marginTop="15dp"
linewarplayout:magin="20"
linewarplayout:itemBg="@drawable/text_bg" >
</com.tang.linewraplayout.LineWrapLayout> protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LineWrapLayout layout = (LineWrapLayout) findViewById(R.id.linewarplayout);
List<String>list = new ArrayList<String>();
String s="";
for(int i=0;i<9;i++)
{
s=s+"X";
String temp ="第"+(i+1)+"个:"+s;
list.add(temp);
}
layout.setData(list);
layout.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onClick(View view) {
// TODO Auto-generated method stub
Log.i("AAA", ((TextView)view).getText().toString());
}
});
}
代码下载:http://download.csdn.net/detail/tangnengwu/7822189
子控件根据父控件行宽自动换行---LineWrapLayout实现
原文地址:http://blog.csdn.net/tangnengwu/article/details/38848577