ACRA : Application crash report for android
- 作用: 为自己的应用找bug
- 使用步骤:参考文档
自定义布局的实现:流程图
参照流程图:当有孩子时,是否需要对孩子控件大小进行布置,如果需要就得重写onMeasure()这个方法调用child.layout()方法。需要孩子控件布局进行控制也要重写onLayout()方法,需要对控件的显示进行控制时要重写onDraw()方法。
一般实现全部构造函数。
重写
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
//临时top
int topmt=0;
int parentWidth = getMeasuredWidth();
//获得孩子个数
int count =getChildCount();
for(int i=0;i
还需要重写onMeasure()
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//获得父亲的宽高
int widthsize=MeasureSpec.getSize(widthMeasureSpec);
int heightsize=MeasureSpec.getSize(heightMeasureSpec);
measureChildren(0, 0);//设置孩子,为0由父亲安排宽高
setMeasuredDimension(widthsize, heightsize);
}
自定义布局的使用:
如果需要切换布局,一般定义一个boolean类型值进行切换
FlowLayout
- 分析:
- 多行摆放
- 单行如果摆不下去,换行摆放
看下效果图:
一下子看到这种布局说真的我无从下手,不知道这个怎么实现,每行个数不一样,列数不一样,后来知道自定义布局可以实现。根据上面的view实现的流程图可以知道,需要对控件的布局、大小进行控制,所以需要重写onLayout()、onMeasure()的方法。再重写方法之前,需要先分析每一行是怎么布局的,以面向对象的思想封装每一行需要的属性、和方法。如下:
行的类
class Line{
//存储孩子
private List mChildViews=new LinkedList();
private int usedWidth;//已经使用过的宽度
private int lineHeight;//行最大的高度
private int maxWidth;//行最大的宽度,父类给的
private int horizontalSpace;//中间的间隔
public Line(int maxWidth,int horizontalSpace){
this.maxWidth=maxWidth;
this.horizontalSpace=horizontalSpace;
}
//判断该行是否能添加view
public boolean canAddView(View view){
//如果使用的宽度+准备加的View的宽度+中间的间隔>最大的宽度,加不上去
//准备加的View的宽度
int childwidth=view.getMeasuredWidth();
int size=mChildViews.size();
if(size==0){
return true;
}else if(usedWidth+childwidth+horizontalSpace>maxWidth){
return false;
}
return true;
}
//添加view到布局
public void addView(View view){
//
int childWidth=view.getMeasuredWidth();
int childHeight=view.getMeasuredHeight();
int size=mChildViews.size();
if(size==0){
//没有孩子 已经使用的宽度
if(childWidth>maxWidth){
usedWidth=maxWidth;
}else{
usedWidth=childWidth;
}
//高度
lineHeight=childHeight;
}else{
//已经使用的宽度
usedWidth=usedWidth+childWidth+horizontalSpace;
//高度
lineHeight=lineHeight>childHeight?lineHeight:childHeight;
}
//加孩子
mChildViews.add(view);
}
//给行布局
public void layout(int left,int top)
{
//给孩子布局
int size=mChildViews.size();
int tmpLeft=0;
//将每一行右侧无法显示的空白部分平分给每一行显示的每个控件
int extraWidth=(int) ((maxWidth-usedWidth)*1f/size+0.5f);
for(int i=0;i0){
//希望孩子再宽点,填充右侧空白
int widthMeasureSpec=MeasureSpec.makeMeasureSpec(childWidth+extraWidth, MeasureSpec.EXACTLY);
int heightMeasureSpec=MeasureSpec.makeMeasureSpec(childHeight,MeasureSpec.EXACTLY);
child.measure(widthMeasureSpec, heightMeasureSpec);
//重新获得宽高
childWidth=child.getMeasuredWidth();
childHeight=child.getMeasuredHeight();
}
int extraHeight=(int) ((lineHeight-childHeight)/2f+0.5f);
int l=left+tmpLeft;
int t=top+extraHeight;
int r=l+childWidth;
int b=t+childHeight;
child.layout(l, t, r, b);
//添加记录
tmpLeft +=childWidth + horizontalSpace;
}
}
}
重写onLayout()方法:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
int left=getPaddingLeft();
int top=getPaddingTop();
//让行进行布局
for(int i=0;i
重写onMeasure()方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//孩子个数记录清空
mLines.clear();
mCurrentLine=null;
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int lineMaxWidth=widthSize-getPaddingLeft()-getPaddingRight();
//测量孩子完成时,就记录到行里面
int count=getChildCount();
for(int i=0;i
在MainActivity中:
public class MainActivity extends Activity {
private FlowLayout layout;
private String []mDatas={"单机游戏","美女","游戏","单机游戏","美女","淘宝","单机游戏","美女","淘宝","游戏" ,"单机游戏","淘宝","游戏","单机游戏","美女","淘宝","游戏","单机游戏","美女","淘宝","游戏" ,"有道","天猫","汽车商城","新闻","运动","熊出没之大逃跑"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout=(FlowLayout) findViewById(R.id.flow_layout);
layout.setPadding(10, 10, 10, 10);
initData();
}
private void initData()
{
for(int i=0;i
使用自定义布局时:
到这里,上图的效果就已经出来,这种布局的逻辑判断有点繁琐,稍有差错就显示不出来了。记得要多看。