Android onLayout()

Called from layout when this view should assign a size and position to each of its children

       onLayout()方法的注释就是安排自己的子View的位置,我们继承View的时候好像很少用到这个玩意。因为只是写一个控件根本不会存在子View的问题。
       接手别人的代码有个FlowLayout,搜索的时候出现历史记录的类似的View,但是换行的时候会出现问题。所以觉得可以自己搞个试试。
       首先要继承自ViewGroup这个类。直接重写方法,会发现一定要重写一个onLayout的方法。

public class FlowLayout extends ViewGroup {

public FlowLayout(Context context) {
    this(context,null);
}

public FlowLayout(Context context, AttributeSet attrs) {
    this(context, attrs,0);
}

public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

}
}

    之前的onMeasure()是对View的测量。这个onLayout()就是对View的位置进行摆放。写个简单的xml


xml布局.png

运行之后发现什么画面没有。这是当然的因为我们什么都没搞。那好现在开始填代码,我们在onLayout()方法中摆放控件。

    int count   = getChildCount() ;
    Log.e(TAG, "onLayout: "+count );
    for(int i =0 ;i<count;i++){
        View child = getChildAt(i);
        child.layout(100*i+100,100*i+100,200*i+200,200*i+200);
    }

       这里是随便选的几个位置放一下,这里的layout四个参数分别是左上右下离父布局的距离。

初设layout.png

这样一看这个简单的代码能实现布局好像有点东西的。既然知道了onLayout()的功能了我们就直接一把梭吧,思路:一个View 挨着一个View 当一行View多的放不下的时候自动换行。两个View之间来电间距。

    int count   = getChildCount() ;
    int indexX = 20;
    int indexY = 20;
    for(int i =0 ;i<count;i++){
        View child = getChildAt(i);
        int width = child.getMeasuredWidth();
        int height = child.getMeasuredHeight();
         if(i==0){
            child.layout(indexX,indexY,indexX+width,indexY+height);
        }else{
            child.layout(indexX,indexY,indexX+width,indexY+height);
        }
        indexX+=width;
    }
}

       一把梭哈,先完成两个的View摆放,这个简单没什么问题。直接放第一个View 初始化一个开始位置(20,20)坐标点,然后开始向右边排。运行起来之后尴尬的事情发生了,UI上啥都没有。我们好像少了什么,一般都要先Measure的吧.ViewGroup中onMeasure主要是来调用measureChildren()方法。通过测量子View的大小然后在自己的View中设置宽高。加上方法,这里其实还有measureChildWithMargins(),这个可以获取到margins。先简单的设置一波。(这里其实要算子View的宽高的总和,再来设置FlowLayout的大小)

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    measureChildren(widthMeasureSpec,heightMeasureSpec);
}

       实现效果如:

初见效果.png

       现在要设置两个View之间的间距,我们可以加一个属性来实现,现在改变一下代码,中间的间隔就出来了。
indexX=indexX+width+padding,下面得看一下换行的效果,思路:当一行容不下要添加的View的时候我们要进行换行,即A+B >ScreenWidth------->height+Y;还是直接走代码吧:

    int count   = getChildCount() ;
    int indexX = 20;
    int indexY = 20;
    for(int i =0 ;i<count;i++){
        View child = getChildAt(i);
        int width = child.getMeasuredWidth();
        int height = child.getMeasuredHeight();
        if(width+indexX > getMeasuredWidth()){
           indexX = 20;
           indexY =indexY+ getChildAt(i-1).getMeasuredHeight()+padding;
        }
        child.layout(indexX,indexY,indexX+width,indexY+height);
        indexX=indexX+width+padding;
    }

       简单的代码就实现了,历史纪录的View,我们可以想想这里是通过xml中自己写的,那岂不是很傻,有时间写好像不如自己把东西画出来,当然当Item数量不固定的时候,好像也挺尴尬的。


再见效果图.png
  • 好吧我们进行第一次改良,需求设计成动态配置View的数量。

     public void addViewWithString(ArrayList<String> list){
      this.removeAllViews();
      for(String string:list) {
          TextView textView = new TextView(mContext);
          textView.setText(string);
          this.addView(textView);
      }
     }
    

       首先移除之前的View,然后把TextView添加上去 ,实现效果


动态添加效果.png

这样看好丑,人家的TextView至少还有背景,这个动态添加的背景怎么搞,当然是在setTextView后面加上setBackground属性啦。当然最好是开一个属性在FlowLayout这个控件上面,让写布局的时候可以进行配置。
       但是问题来了,显示没毛病我要点击怎么办?设置一个点击事件吧,我们把方法改进一下直接上代码:

public void initDate(ArrayList<String> list){
    this.removeAllViews();
    for(int i = 0;i<list.size();i++){
        addViewWithString(list.get(i),i);
    }

}


public void addViewWithString(final String name , final int position){
        TextView textView = new TextView(mContext);
        textView.setText(name);
        textView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if(iChildClickListener!=null){
                    iChildClickListener.childClickListener(name,position);
                }
            }
        });
        this.addView(textView);

}
interface IChildClickListener{
    void childClickListener(String name,int position);
}
IChildClickListener iChildClickListener ;

public void setiChildClickListener(IChildClickListener listener){
    this.iChildClickListener = listener;
}

外部调用:

 FlowLayout flowLayout = findViewById(R.id.flowLayout);
     flowLayout.initDate(list);
    flowLayout.setiChildClickListener(new FlowLayout.IChildClickListener() {
        @Override
        public void childClickListener(String name, int position) {
            Toast.makeText(MainActivity.this,"第"+position+"个"+"--->"+name,Toast.LENGTH_LONG).show();
        }
    });

那么就可以实现点击事件以及效果了。好了,把代码整理一下加上背景。


加上点击效果.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容