<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android仿淘寶搜索歷史界面功能

          共 7131字,需瀏覽 15分鐘

           ·

          2021-08-03 19:12

          一 關(guān)于自定義viewGroup

          自定義viewGroup需要繼承viewGroup,并重寫抽象方法onLayout,
          負(fù)責(zé)子view位置的擺放。onMeasure()方法則完成對子view的測量過程,
          其中,對子view的測量涉及到MeasureSpec,包括父布局的MeasureSpec
          和子view的MeasureSpec。對子view的寬高測量完成后,相加即為
          viewGroup的寬高,再通過setMeasuredDimension()
          這個方法來保存測量好的寬高。

          二 關(guān)于MeasureSpec

          MeasureSpec代表一個32位int值,高2位代表SpecMode,低30位代碼SpecSize,SpecMode是指測量模式,而SpecSize是指在某種測量模式下地規(guī)格地大小。

          SpecMode有三類,每一類都表示特殊的含義,如下所示。

          UNSPECIFIED
          父容器不對View有任何限制,要多大給多大,這種情況一般用于系統(tǒng)內(nèi)部,表示一種測量狀態(tài)。

          EXACTLY
          父容器以及檢測出View所需要的大小,這個時候View的最終大小就是SpecSize所指定的值。它對應(yīng)于LayoutParams中的match_parent和具體數(shù)值這兩種模式。

          AT_MOST
          父容器指定了一個可用大小即SpecSize,View的大小不能大于這個值,具體是什么要看不同View的具體實現(xiàn)。它對應(yīng)于LayoutParams中的wrap_content。


          三 關(guān)于流式布局Measure流程


          1.遍歷所有的子view,根據(jù)父布局的MeasureSpec還有子view的
          LayoutParams 算出子view的MesureSpec

          LayoutParams childLP = childView.getLayoutParams();
          int childWidthMesureSpec =getChildMeasureSpec(widthMeasureSpec,paddingLeft+paddingRight,childLP.width);
          int childHeightMesureSpec =getChildMeasureSpec(heightMeasureSpec,paddingBottom+paddingTop,childLP.height);
          childView.measure(childWidthMesureSpec,childHeightMesureSpec);

          2.通過寬度來判斷是否需要換行,通過換行后的每行的行高來獲取整個viewGroup的行高
          如果寬度不夠,則需換行

          if (childMesuredWidth + lineWidthUsed +mHorizontalSpacing > selfWidth){
          allLines.add(lineViews);
          lineHeights.add(lineHeight);
          //一旦換行,可以判斷當(dāng)前所需的寬高了
          parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed+mHorizontalSpacing);
          parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;
          lineViews =new ArrayList<>();
          lineWidthUsed =0;
          lineHeight =0;
          }

          3.根據(jù)子View的度量結(jié)果,來重新度量自己ViewGroup
          作為一個ViewGroup,它自己也是一個View,它的大小也需要根據(jù)它的父親給它提供的寬高來度量

          int widthMode = MeasureSpec.getMode(widthMeasureSpec);
          int heightMode = MeasureSpec.getMode(heightMeasureSpec);
          int realWidth = (widthMode == MeasureSpec.EXACTLY)? selfWidth:parentNeededWidth;
          int realHeight = (heightMode == MeasureSpec.EXACTLY)?selfHeight:parentNeededHeight;
          setMeasuredDimension(realWidth,realHeight);

          四 關(guān)于layout流程

          measure完成后,每個子view的寬高通過view.getMeasuredHeight/Width 
          來獲得,只需算出距離viewGroup左邊和頂部的距離傳入即可。

          int lineCount =allLines.size();
          int curL =0;
          int curT =0;
          for (int i =0;i
          List lineViews =allLines.get(i);
          int lineHeight =lineHeights.get(i);
          for (int j =0;j
          View view = lineViews.get(j);
          int left = curL;
          int top = curT;
          int bottom = top + view.getMeasuredHeight();
          int right = left + view.getMeasuredWidth();
          view.layout(left,top,right,bottom);
          curL = right +mHorizontalSpacing;
          }
          curL =0;
          curT = curT + lineHeight +mVerticalSpacing;

          五 關(guān)于源代碼FlowLayout源代碼
          public class FlowLayoutextends ViewGroup {
          private int mHorizontalSpacing =dp2px(16); //每個item橫向間距
          private int mVerticalSpacing =dp2px(8); //每個item橫向間距
          private List>allLines ; // 記錄所有的行,一行一行的存儲
          private ListlineHeights =new ArrayList<>(); // 記錄每一行的行高
          boolean isMeasuredOver =false;
          public FlowLayout(Context context) {
          super(context);
          }
          public FlowLayout(Context context, AttributeSet attrs) {
          super(context, attrs);
          }
          public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          }
          @Override
          protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          initMeasureParams();
          int childCount = getChildCount();
          int paddingLeft = getPaddingLeft();
          int paddingRight = getPaddingRight();
          int paddingTop = getPaddingTop();
          int paddingBottom = getPaddingBottom();
          int selfWidth = MeasureSpec.getSize(widthMeasureSpec); //ViewGroup解析的寬度
          int selfHeight = MeasureSpec.getSize(heightMeasureSpec); // ViewGroup解析的高度
          List lineViews =new ArrayList<>(); //保存一行中的所有的view
          int lineWidthUsed =0; //記錄這行已經(jīng)使用了多寬的size
          int lineHeight =0; // 一行的行高
          int parentNeededWidth =0; // measure過程中,子View要求的父ViewGroup的寬
          int parentNeededHeight =0; // measure過程中,子View要求的父ViewGroup的高
          for (int i =0;i
          View childView = getChildAt(i);
          LayoutParams childLP = childView.getLayoutParams();
          int childWidthMesureSpec =getChildMeasureSpec(widthMeasureSpec,paddingLeft+paddingRight,childLP.width);
          int childHeightMesureSpec =getChildMeasureSpec(heightMeasureSpec,paddingBottom+paddingTop,childLP.height);
          childView.measure(childWidthMesureSpec,childHeightMesureSpec);
          //獲取子view的寬高
          int childMesuredWidth = childView.getMeasuredWidth();
          int childMesuredHeight = childView.getMeasuredHeight();
          //通過寬度來判斷是否需要換行,通過換行后的每行的行高來獲取整個viewGroup的行高
          //如果寬度不夠,則需換行
          if (childMesuredWidth + lineWidthUsed +mHorizontalSpacing > selfWidth){
          allLines.add(lineViews);
          lineHeights.add(lineHeight);
          //一旦換行,可以判斷當(dāng)前所需的寬高了
          parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed+mHorizontalSpacing);
          parentNeededHeight = parentNeededHeight + lineHeight +mVerticalSpacing;
          lineViews =new ArrayList<>();
          lineWidthUsed =0;
          lineHeight =0;
          }
          // view 是分行l(wèi)ayout的,所以要記錄每一行有哪些view,這樣可以方便layout布局
          lineViews.add(childView);
          lineWidthUsed = lineWidthUsed + childMesuredWidth +mHorizontalSpacing;
          lineHeight = Math.max(lineHeight,childMesuredHeight);
          //childview 最后一行
          if (i == childCount -1){
          lineHeights.add(lineHeight);
          allLines.add(lineViews);
          parentNeededWidth = Math.max(parentNeededWidth,lineWidthUsed );
          parentNeededHeight += lineHeight;
          }
          //根據(jù)子View的度量結(jié)果,來重新度量自己ViewGroup
          // 作為一個ViewGroup,它自己也是一個View,它的大小也需要根據(jù)它的父親給它提供的寬高來度量
          int widthMode = MeasureSpec.getMode(widthMeasureSpec);
          int heightMode = MeasureSpec.getMode(heightMeasureSpec);
          int realWidth = (widthMode == MeasureSpec.EXACTLY)? selfWidth:parentNeededWidth;
          int realHeight = (heightMode == MeasureSpec.EXACTLY)?selfHeight:parentNeededHeight;
          setMeasuredDimension(realWidth,realHeight);
          isMeasuredOver =true;
          }
          }
          private void initMeasureParams() {
          allLines =new ArrayList<>();
          lineHeights =new ArrayList<>();
          }
          @Override
          protected void onLayout(boolean changed, int l, int t, int r, int b) {
          int lineCount =allLines.size();
          int curL =0;
          int curT =0;
          for (int i =0;i
          List lineViews =allLines.get(i);
          int lineHeight =lineHeights.get(i);
          for (int j =0;j
          View view = lineViews.get(j);
          int left = curL;
          int top = curT;
          int bottom = top + view.getMeasuredHeight();
          int right = left + view.getMeasuredWidth();
          view.layout(left,top,right,bottom);
          curL = right +mHorizontalSpacing;
          }
          curL =0;
          curT = curT + lineHeight +mVerticalSpacing;
          }
          }
          public static int dp2px(int dp) {
          return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
              }}

          六 項目運行截圖


          源碼地址:
          (https://github.com/doubizhu/flowlayout)

          到這里就結(jié)束啦。
          瀏覽 186
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  AV第一福利大全导航 | 久久精品黄色电影 | 日韩无码高清免费 | 黄色大片在线免费观看 | 五月天成人激情视频 |