真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android自定義流式布局/自動(dòng)換行布局實(shí)例

最近,Google開源了一個(gè)流式排版庫“FlexboxLayout”,功能強(qiáng)大,支持多種排版方式,如各種方向的自動(dòng)換行等,具體資料各位可搜索學(xué)習(xí)^_^。

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括臨夏網(wǎng)站建設(shè)、臨夏網(wǎng)站制作、臨夏網(wǎng)頁制作以及臨夏網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,臨夏網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到臨夏省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

由于我的項(xiàng)目中,只需要從左到右S型的自動(dòng)換行,需求效果圖如下:

Android自定義流式布局/自動(dòng)換行布局實(shí)例

使用FlexboxLayout這個(gè)框架未免顯得有些臃腫,所以自己動(dòng)手寫了一個(gè)流式ViewGroup。

安卓中自定義ViewGroup的步驟是:

1. 新建一個(gè)類,繼承ViewGroup

2. 重寫構(gòu)造方法

3. 重寫onMeasure、onLayout方法

onMeasuer方法里一般寫測量子View寬高、確定此控件寬高的代碼;onLayout方法則是確定子View如何擺放(排版)。

代碼如下:

  import android.content.Context;
  import android.util.AttributeSet;
  import android.view.View;
  import android.view.ViewGroup;

  public class FlexBoxLayout extends ViewGroup {

    private int mScreenWidth;
    private int horizontalSpace, verticalSpace;
    private float mDensity;//設(shè)備密度,用于將dp轉(zhuǎn)為px

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

    public FlexBoxLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
      //獲取屏幕寬高、設(shè)備密度
      mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
      mDensity = context.getResources().getDisplayMetrics().density;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      //確定此容器的寬高
      int widthMode = MeasureSpec.getMode(widthMeasureSpec);
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
      int heightMode = MeasureSpec.getMode(heightMeasureSpec);
      int heightSize = MeasureSpec.getSize(heightMeasureSpec);

      //測量子View的寬高
      int childCount = getChildCount();
      View child = null;
      //子view擺放的起始位置
      int left = getPaddingLeft();
      //一行view中將最大的高度存于此變量,用于子view進(jìn)行換行時(shí)高度的計(jì)算
      int maxHeightInLine = 0;
      //存儲(chǔ)所有行的高度相加,用于確定此容器的高度
      int allHeight = 0;
      for (int i = 0; i < childCount; i++) {
        child = getChildAt(i);
        //測量子View寬高
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
        //兩兩對比,取得一行中最大的高度
        if (child.getMeasuredHeight() + child.getPaddingTop() + child.getPaddingBottom() > maxHeightInLine) {
          maxHeightInLine = child.getMeasuredHeight() + child.getPaddingTop() + child.getPaddingBottom();
        }
        left += child.getMeasuredWidth() + dip2px(horizontalSpace) + child.getPaddingLeft() + child.getPaddingRight();
        if (left >= widthSize - getPaddingRight() - getPaddingLeft()) {//換行
          left = getPaddingLeft();
          //累積行的總高度
          allHeight += maxHeightInLine + dip2px(verticalSpace);
          //因?yàn)閾Q行了,所以每行的最大高度置0
          maxHeightInLine = 0;
        }
      }
      //再加上最后一行的高度,因?yàn)橹暗母叨壤鄯e條件是換行
      //最后一行沒有換行操作,所以高度應(yīng)該再加上
      allHeight += maxHeightInLine;

      if (widthMode != MeasureSpec.EXACTLY) {
        widthSize = mScreenWidth;//如果沒有指定寬,則默認(rèn)為屏幕寬
      }

      if (heightMode != MeasureSpec.EXACTLY) {//如果沒有指定高度
        heightSize = allHeight + getPaddingBottom() + getPaddingTop();
      }

      setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
     if (changed) {
       //擺放子view
       View child = null;
       //初始子view擺放的左上位置
       int left = getPaddingLeft();
       int top = getPaddingTop();
       //一行view中將最大的高度存于此變量,用于子view進(jìn)行換行時(shí)高度的計(jì)算
       int maxHeightInLine = 0;
       for (int i = 0, len = getChildCount(); i < len; i++) {
         child = getChildAt(i);
         //從第二個(gè)子view開始算起
         //因?yàn)榈谝粋€(gè)子view默認(rèn)從頭開始擺放
         if (i > 0) {
           //兩兩對比,取得一行中最大的高度
         if (getChildAt(i - 1).getMeasuredHeight() > maxHeightInLine) {
             maxHeightInLine = getChildAt(i - 1).getMeasuredHeight();
           }
           //當(dāng)前子view的起始left為 上一個(gè)子view的寬度+水平間距
           left += getChildAt(i - 1).getMeasuredWidth() + dip2px(horizontalSpace);
           if (left + child.getMeasuredWidth() >= getWidth() - getPaddingRight() - getPaddingLeft()) {//這一行所有子view相加的寬度大于容器的寬度,需要換行
             //換行的首個(gè)子view,起始left應(yīng)該為0+容器的paddingLeft
             left = getPaddingLeft();
             //top的位置為上一行中擁有最大高度的某個(gè)View的高度+垂直間距
             top += maxHeightInLine + dip2px(verticalSpace);
             //將上一行View的最大高度置0
             maxHeightInLine = 0;
           }
         }
         //擺放子view
         child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
       }
     }
   }

    /**
     * dp轉(zhuǎn)為px
     *
     * @param dpValue
     * @return
     */
    private int dip2px(float dpValue) {
      return (int) (dpValue * mDensity + 0.5f);
    }

    /**
     * 設(shè)置子view間的水平間距 單位dp
     *
     * @param horizontalSpace
     */
    public void setHorizontalSpace(int horizontalSpace) {
      this.horizontalSpace = horizontalSpace;
    }

    /**
     * 設(shè)置子view間的垂直間距 單位dp
     *
     * @param verticalSpace
     */
    public void setVerticalSpace(int verticalSpace) {
      this.verticalSpace = verticalSpace;
    }
  }  

使用如下:

xml文件:

    
      
      ……

    

Activity里的代碼:

  FlexBoxLayout flexBoxLayout = (FlexBoxLayout) findViewById(R.id.flex_box_layout);
  flexBoxLayout.setHorizontalSpace(10);//不設(shè)置默認(rèn)為0
  flexBoxLayout.setVerticalSpace(10);//不設(shè)置默認(rèn)為0

運(yùn)行效果如圖:

Android自定義流式布局/自動(dòng)換行布局實(shí)例

本項(xiàng)目Demo地址:

https://github.com/zengd0/FlexBoxLayout

補(bǔ)充知識:Android 流式布局(修改版) 當(dāng)達(dá)到兩行,隱藏多余的

我就廢話不多說了,還是直接看代碼吧!

public class SearchLayout extends LinearLayout {

  private final int mParentWidth;
  private float textSize;
  private boolean textColor;
  private boolean background;
  private boolean isHide = true;

  public void setHide(boolean hide) {
    isHide = hide;
  }

  public SearchLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    //獲取屏幕的寬度
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    mParentWidth = metrics.widthPixels - dip2px(16f);
    //自定義屬性
    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SearchLayout);
    background = array.getBoolean(R.styleable.SearchLayout_Sear_background,false);
    textColor = array.getBoolean(R.styleable.SearchLayout_Sear_textColor, false);
    textSize = array.getDimension(R.styleable.SearchLayout_Sear_textSize, 0);
    //方向?yàn)榭v向
    setOrientation(VERTICAL);
  }

  //移除子控件
  public void removeView() {
    removeAllViews();
  }

  //流式布局
  public void setData(List data) {
    if (data.isEmpty()){
      return;
    }
    //獲取一個(gè)子布局
    LinearLayout linearLayout = getLinearLayout();
    for (int i = 0; i < data.size(); i++) {
      //標(biāo)題
      final String name = data.get(i);
      //已存在的寬度
      int numBar = 0;
      //子控件的個(gè)數(shù)
      int count = linearLayout.getChildCount();
      for (int j = 0; j < count; j++) {
        //一個(gè)一個(gè)獲取
        ThemeTextView textView = (ThemeTextView) linearLayout.getChildAt(j);
        //獲取左外邊距
        LayoutParams params = (LayoutParams) textView.getLayoutParams();
        int leftWidth = params.leftMargin;
        int rightWidth = params.rightMargin;
        //獲取寬高
        textView.measure(getMeasuredWidth(), getMeasuredHeight());
        //計(jì)算已存在的寬度
        numBar += textView.getMeasuredWidth()+leftWidth+rightWidth;
      }
      //獲取一個(gè)子控件
      ThemeTextView text = getText();
      //給每一個(gè)控件設(shè)置點(diǎn)擊事件
      text.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
          if (onItemTitleClickListener != null){
            onItemTitleClickListener.onItemTitle(name);
          }
        }
      });
      //賦值
      text.setText(name);
      //獲取寬高
      text.measure(getMeasuredWidth(), getMeasuredHeight());
      //當(dāng)前控件的寬度
      int textWidth = text.getMeasuredWidth() + text.getPaddingLeft() + text.getPaddingRight();
      //判斷是否超過屏幕
      if (isHide && getChildCount() == 2){
        ImageView imageView = getMore(false);
        LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams();
        int leftM = layoutParams.leftMargin;
        int rightM = layoutParams.rightMargin;
        imageView.measure(getMeasuredWidth(), getMeasuredHeight());
        int width = imageView.getMeasuredWidth() + imageView.getPaddingLeft() + imageView.getPaddingRight();
        int imageWidth = leftM + rightM + width;
        if (numBar + textWidth + imageWidth >= mParentWidth){
          if (numBar + textWidth + imageWidth > mParentWidth){
            imageView.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                if (onMoreClickListener != null){
                  onMoreClickListener.onShowMore(isHide);
                }
              }
            });
            linearLayout.addView(imageView);
            return;
          } else {
            imageView.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                if (onMoreClickListener != null){
                  onMoreClickListener.onShowMore(isHide);
                }
              }
            });
            linearLayout.addView(text);
            linearLayout.addView(imageView);
            return;
          }
        }else {
          if (i + 1 <= data.size()-1) {
            String title = data.get(i + 1);
            ThemeTextView themeTextView = getText();
            themeTextView.setText(title);
            themeTextView.measure(getMeasuredWidth(),getMeasuredHeight());
            int themeTextViewWidth = themeTextView.getMeasuredWidth() + themeTextView.getPaddingLeft() + themeTextView.getPaddingRight();
            if (mParentWidth >= numBar + textWidth + imageWidth + themeTextViewWidth ){
              linearLayout.addView(text);
              continue;
            }else {
              imageView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                  if (onMoreClickListener != null){
                    onMoreClickListener.onShowMore(isHide);
                  }
                }
              });
              linearLayout.addView(text);
              linearLayout.addView(imageView);
              return;
            }
          }
        }
      }


      if (i == data.size() - 1 && (getChildCount() >= 3 || (mParentWidth < numBar + textWidth) && getChildCount() == 2)){
        ImageView imageView = getMore(true);
        LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams();
        int leftM = layoutParams.leftMargin;
        int rightM = layoutParams.rightMargin;
        imageView.measure(getMeasuredWidth(), getMeasuredHeight());
        int width = imageView.getMeasuredWidth() + imageView.getPaddingLeft() + imageView.getPaddingRight();
        int imageWidth = leftM + rightM + width;
        imageView.setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
            if (onMoreClickListener != null){
              onMoreClickListener.onShowMore(isHide);
            }
          }
        });
        if (mParentWidth >= numBar + textWidth + imageWidth){
          linearLayout.addView(text);
          linearLayout.addView(imageView);
        }else {
          if (mParentWidth >= numBar + textWidth){
            linearLayout.addView(text);
            linearLayout = getLinearLayout();
            linearLayout.addView(imageView);
          }else {
            linearLayout = getLinearLayout();
            linearLayout.addView(text);
            linearLayout.addView(imageView);
          }
        }
        return;
      }

      if (mParentWidth >= numBar + textWidth) {
        //沒有,繼續(xù)添加
        linearLayout.addView(text);
      } else {
        //否者,重新獲取一個(gè)子布局,再添加
        linearLayout = getLinearLayout();
        linearLayout.addView(text);
      }

    }
  }

  public LinearLayout getLinearLayout() {
    //創(chuàng)建LinearLayout布局
    LinearLayout linearLayout = new LinearLayout(getContext());
    //設(shè)置寬高
    LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    linearLayout.setLayoutParams(params);
    //添加到主布局中
    this.addView(linearLayout);
    return linearLayout;
  }

  public ThemeTextView getText() {
    //創(chuàng)建TextView控件
    //設(shè)置字體大小,顏色,內(nèi)邊距
    ThemeTextView themeTextView = new ThemeTextView(getContext());
    themeTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX , textSize);
    themeTextView.setMaxEms(7);
    themeTextView.setLines(1);
    themeTextView.setEllipsize(TextUtils.TruncateAt.END);
    themeTextView.setPadding(dip2px(8), dip2px(4), dip2px(8), dip2px(4));
    if (textColor){//可以根據(jù)自己的需求修改判斷
    	themeTextView.setTextColor(ContextCompat.getColor(getContext(),R.color.day_text_color_thirdly));
    }else {
      themeTextView.setTextColor(ContextCompat.getColor(getContext(),R.color.day_text_color_thirdly));
    }

    if (background){
       themeTextView.setBackgroundResource(R.drawable.border_search_background_day);
    }
    //設(shè)置寬高
    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    //外邊距
    params.setMargins(dip2px(8),dip2px(8),dip2px(8),dip2px(8));
    themeTextView.setLayoutParams(params);
    return themeTextView;
  }

  public ImageView getMore(boolean isHide){
    ImageView imageView = new ImageView(getContext());
    if (background){
      imageView.setBackgroundResource(R.drawable.border_search_background_day);
    }
    imageView.setImageResource(R.drawable.icon_more);

    if (isHide){
      imageView.setRotation(180f);
    }
	  imageView.setColorFilter(ContextCompat.getColor(getContext(),R.color.day_text_color_primary));
    imageView.setPadding(dip2px(6), dip2px(6), dip2px(7), dip2px(7));

    //設(shè)置寬高
    LayoutParams params = new LayoutParams(ConfigSingleton.dip2px(27), ConfigSingleton.dip2px(27));
    //外邊距
    params.setMargins(dip2px(8),dip2px(8),dip2px(8),dip2px(8));
    imageView.setLayoutParams(params);
    return imageView;
  }

  public interface OnItemTitleClickListener{
    void onItemTitle(String title);
  }

  public interface OnMoreClickListener{
    void onShowMore(boolean ishide);
  }

  private OnItemTitleClickListener onItemTitleClickListener;
  private OnMoreClickListener onMoreClickListener;

  public void setOnItemTitleClickListener(OnItemTitleClickListener onItemTitleClickListener) {
    this.onItemTitleClickListener = onItemTitleClickListener;
  }

  public void setOnMoreClickListener(OnMoreClickListener onMoreClickListener) {
    this.onMoreClickListener = onMoreClickListener;
  }

	public int dip2px(float dipValue) {
			float scale = getContext().getResources().getDisplayMetrics().density;
			return (int) (dipValue * scale + 0.5f);
		}
}

attrs文件:

 
    
    
    
  

以上這篇Android自定義流式布局/自動(dòng)換行布局實(shí)例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持創(chuàng)新互聯(lián)。


當(dāng)前文章:Android自定義流式布局/自動(dòng)換行布局實(shí)例
網(wǎng)站URL:http://weahome.cn/article/gsejhh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部