国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android 簡單實現一個流式布局的示例

2019-10-22 18:15:39
字體:
來源:轉載
供稿:網友

本篇文章主要介紹了Android 簡單實現一個流式布局的示例,分享給大家,具體如下:

Android,流式布局,android流式布局實現

流式布局應該是我們很常見的一種布局了,在很多場景下都會遇到它,例如:標簽之類的功能等。用輪子不如造輪子來的爽,這里自己簡單的實現下流式布局:

  1. onMeasure
  2. onLayout

通過以上兩個方法我們就可以完成對流式布局的基本操作:

onMeasure

  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    // 獲得它的父容器為它設置的測量模式和大小    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);    int modeWidth = MeasureSpec.getMode(widthMeasureSpec);    int modeHeight = MeasureSpec.getMode(heightMeasureSpec);    // 如果是warp_content情況下,記錄寬和高    int width = 0;    int height = 0;    //記錄每一行的寬度,width不斷取最大寬度    int lineWidth = 0;    //記錄每一行的寬度,不斷累加每行最大高度獲取height    int lineHeight = 0;    //獲取子View的數量    int childCount = getChildCount();    //遍歷每個子元素    for (int i = 0; i < childCount; i++) {      //獲取每一個子View      View childView = getChildAt(i);      //測量每一個子View的寬和高      measureChild(childView,widthMeasureSpec,heightMeasureSpec);      //得到子View的lp      LayoutParam lp = (LayoutParam) childView.getLayoutParams();      //當前子View實際占據的寬度      int childWidth = childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;      //當前子View實際占據的高度      int childHeight = childView.getMeasuredHeight() + lp.bottomMargin + lp.topMargin;      //如果加入當前childView,超出最大寬度,則得到目前最大寬度給width,類加height 然后開啟新行      if (lineWidth + childWidth > sizeWidth) {        // 取最大的寬度        width = Math.max(lineWidth, childWidth);        //重新開啟新行,重新計算        lineWidth = childWidth;        //疊加當前高度        height += childHeight;        //記錄下一行高度        lineHeight = childHeight;      }else {        // 累加值lineWidth,lineHeight取最大高度        lineWidth += childWidth;        lineHeight = Math.max(lineHeight,childHeight);      }      // 如果是最后一個,則將當前記錄的最大寬度和當前lineWidth做比較      if (i == childCount - 1) {        width = Math.max(width,lineWidth);        height += lineHeight;      }    }    setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY?sizeWidth:width,modeHeight == MeasureSpec.EXACTLY?sizeHeight:height);  }

在onMeasure方法中負責設置子控件的測量模式和大小 根據所有子控件設置自己的寬和高,一旦寬度超出最大寬度便進行換行處理。高度不斷累加從而獲取最終高度。

onLayout

  //存儲所有的View,按行記錄  private List<List<View>> mAllViews = new ArrayList<>();  //記錄每一行的最大高度  private List<Integer> mLineHeight = new ArrayList<>();  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    mAllViews.clear();    mLineHeight.clear();    int lineWidth = 0;    int lineHeight = 0;    int width = getWidth();    int childCount = getChildCount();    // 存儲每一行所有的childView    List<View> lineViews = new ArrayList<>();    for (int i = 0; i < childCount; i++) {      View childView = getChildAt(i);      LayoutParam lp = (LayoutParam) childView.getLayoutParams();      int childWidth = childView.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;      int childHeight = childView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;      if (lineWidth + childWidth > width) {        // 記錄這一行所有的View以及最大高度        mLineHeight.add(lineHeight);        // 將當前行的childView保存,然后開啟新的ArrayList保存下一行的childView        mAllViews.add(lineViews);        lineWidth = 0;        lineViews = new ArrayList<>();      }      //如果不需要換行,則累加      lineWidth += childWidth;      lineHeight = Math.max(lineHeight,childHeight);      lineViews.add(childView);    }    // 記錄最后一行    mAllViews.add(lineViews);    mLineHeight.add(lineHeight);    int left = 0;    int top = 0;    // 得到總行數    int size = mAllViews.size();    for (int i = 0; i < size; i++) {      // 每一行的所有的views      lineViews = mAllViews.get(i);      // 當前行的最大高度      lineHeight = mLineHeight.get(i);      for (View view : lineViews) {        LayoutParam lp = (LayoutParam) view.getLayoutParams();        //計算childView的left,top,right,bottom        int lc = left + lp.leftMargin;        int tc = top + lp.topMargin;        int rc = lc + view.getMeasuredWidth();        int bc = tc + view.getMeasuredHeight();        view.layout(lc,tc,rc,bc);        left += view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;      }      left = 0;      top += lineHeight;    }  }

通過onLayout方法給子View布局,前提,我們必須得知道每個子View的寬度和高度。所以我們先要在onMeasure的時候,測量一下每個子View的具體大小。

測試

public class MainActivity extends AppCompatActivity {  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    FlowLayout flowLayout = ((FlowLayout) findViewById(R.id.flowLayout));    FlowLayout.LayoutParam params = new    FlowLayout.LayoutParam(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);    params.setMargins(10,10,10,10);    for (int i = 0; i < 10; i++) {      TextView textView = new TextView(this);      textView.setPadding(i * 10,10,i * 10,10);      textView.setBackgroundColor(Color.BLUE);      textView.setText("哈哈哈哈");      textView.setTextColor(Color.WHITE);      textView.setLayoutParams(params);      flowLayout.addView(textView);    }  }}

這里我們要注意下FlowLayout.LayoutParam params = new FlowLayout.LayoutParam(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);這個方法,有的小伙伴在寫的過程中可能點不出來這個方法,那是因為這個方法是需要我們自己寫一個靜態內部類來實現。

@Override  protected LayoutParams generateDefaultLayoutParams() {    return new LayoutParam(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  }  @Override  public LayoutParams generateLayoutParams(AttributeSet attrs) {    return new LayoutParam(getContext(),attrs);  }  @Override  protected LayoutParams generateLayoutParams(LayoutParams p) {    return new LayoutParam(p);  }  public static class LayoutParam extends MarginLayoutParams{    public LayoutParam(Context c, AttributeSet attrs) {      super(c, attrs);    }    public LayoutParam(@Px int width, @Px int height) {      super(width, height);    }    public LayoutParam(MarginLayoutParams source) {      super(source);    }    public LayoutParam(LayoutParams source) {      super(source);    }  }

好了,這樣一個簡單的流式布局就結束了,有時候自己親自敲一遍將它實現,才發現會學到很多。這里測試的代碼是循環加入的View,大家也可以嘗試的寫個類似適配器的方式去實現。貼上源碼供參考。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 柯坪县| 香格里拉县| 满城县| 大埔县| 巴南区| 浦北县| 饶河县| 民权县| 彭山县| 洛南县| 大化| 贵德县| 九龙城区| 崇信县| 安岳县| 大悟县| 军事| 旬邑县| 陆良县| 翁牛特旗| 麻阳| 建昌县| 平原县| 凯里市| 西乡县| 廊坊市| 拜泉县| 中卫市| 霍城县| 安龙县| 宁德市| 临泉县| 张家港市| 巴彦淖尔市| 武宣县| 芜湖市| 开远市| 疏附县| 前郭尔| 平昌县| 威信县|