亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android自定義ViewGroup實現(xiàn)標簽浮動效果

 更新時間:2016年06月16日 11:32:20   投稿:lijiao  
這篇文章主要為大家詳細介紹了Android自定義ViewGroup實現(xiàn)標簽浮動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前面在學習鴻洋大神的一些自定義的View文章,看到了自定義ViewGroup實現(xiàn)浮動標簽,初步看了下他的思路以及結(jié)合自己的思路完成了自己的浮動標簽的自定義ViewGroup。目前實現(xiàn)的可以動態(tài)添加標簽、可點擊。效果圖如下:

1、思路
 首先在onMeasure方法中測量ViewGroup的寬和高,重點是處理當我們自定義的ViewGroup設(shè)置為wrap_content的情況下,如何去測量其大小的問題。當我們自定義的ViewGroup設(shè)置為wrap_content時,我們需要讓子View先去測量自己,當子View測量完后,再通過子View的getMeasuredWidth和getMeasureHeight方法獲得其子View的寬和高。每次在測量一個子View之前,都需要判斷如果加入該子View,當前行是否能夠容納下該子View,如果不能,則需要新開一行,并記錄下當前行的最大高度。
 在onLayout方法中,核心人物是給每個子View擺放位置,也就是為該ViewGroup中每個子View找到盒子模型上面的兩個點也就是左上角和右下角,即點(l,t)和點(r,b),確定了兩個點,子View的位置也就確定了。 

2、實現(xiàn)
 基本思路有了就可以嘗試實現(xiàn)了,代碼如下:
 自定義的ViewGroup: 

/**
 * 流式標簽(動態(tài)的,根據(jù)傳入的數(shù)據(jù)動態(tài)添加標簽)
 */
public class DynamicTagFlowLayout extends ViewGroup {
 
 private List<String> mTags = new ArrayList<String>();
 
 public DynamicTagFlowLayout(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 }

 public DynamicTagFlowLayout(Context context, AttributeSet attrs) {
 super(context, attrs);
 }

 public DynamicTagFlowLayout(Context context) {
 super(context);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 
 //當前ViewGroup的總高度
 int totalHeight= 0;
 //所有行中的最大寬度
 int maxLineWidth = 0;
 
 //當前行的最大高度
 int lineMaxHeight = 0;
 //當前行的總寬度
 int currentLineWidth = 0;
 
 //每個childView所占用的寬度
 int childViewWidthSpace = 0;
 //每個childView所占用的高度
 int childViewHeightSpace = 0;
 
 int count = getChildCount();
 MarginLayoutParams layoutParams;
 
 for(int i = 0; i < count; i++){
  View child = getChildAt(i);
  
  if(child.getVisibility() != View.GONE){//只有當這個View能夠顯示的時候才去測量
  //測量每個子View,以獲取子View的寬和高
  measureChild(child, widthMeasureSpec, heightMeasureSpec);
  
  layoutParams = (MarginLayoutParams) child.getLayoutParams();
  
  childViewWidthSpace = child.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;
  childViewHeightSpace = child.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin;
  
  if(currentLineWidth + childViewWidthSpace > widthSize){//表示如果當前行再加上現(xiàn)在這個子View,就會超出總的規(guī)定寬度,需要另起一行
   totalHeight += lineMaxHeight;
   if(maxLineWidth < currentLineWidth){//如果行的最長寬度發(fā)生了變化,更新保存的最長寬度
   maxLineWidth = currentLineWidth;
   }
   currentLineWidth = childViewWidthSpace;//另起一行后,需要重置當前行寬
   lineMaxHeight = childViewHeightSpace;
  }else{//表示當前行可以繼續(xù)添加子元素
   currentLineWidth += childViewWidthSpace;
   if(lineMaxHeight < childViewHeightSpace){
   lineMaxHeight = childViewHeightSpace;
   }
  }
  }
 }
 
 setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : maxLineWidth, heightMode == MeasureSpec.EXACTLY ? heightSize : totalHeight);
 
 }

 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
 //當前是第幾行
 int currentLine = 1;
 //存放每一行的最大高度
 List<Integer> lineMaxHeightList = new ArrayList<Integer>();
 
 //每個childView所占用的寬度
 int childViewWidthSpace = 0;
 //每個childView所占用的高度
 int childViewHeightSpace = 0;
 
 //當前行的最大高度
 int lineMaxHeight = 0;
 //當前行的總寬度
 int currentLineWidth = 0;
 
 int count = getChildCount();
 MarginLayoutParams layoutParams;
 
 for(int i = 0; i < count; i++){
  int cl= 0, ct = 0, cr = 0, cb = 0;
  View child = getChildAt(i);
  if(child.getVisibility() != View.GONE){//只有當這個View能夠顯示的時候才去測量
  
  layoutParams = (MarginLayoutParams) child.getLayoutParams();
  childViewWidthSpace = child.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;
  childViewHeightSpace = child.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin;
  
  System.out.println("getWidth()---->"+getWidth());
  
  if(currentLineWidth + childViewWidthSpace > getWidth()){//表示如果當前行再加上現(xiàn)在這個子View,就會超出總的規(guī)定寬度,需要另起一行
   lineMaxHeightList.add(lineMaxHeight);//此時先將這一行的最大高度加入到集合中
   //新的一行,重置一些參數(shù)
   currentLine++;
   currentLineWidth = childViewWidthSpace;
   lineMaxHeight = childViewHeightSpace;
   
   cl = layoutParams.leftMargin;
   if(currentLine > 1){
   for(int j = 0; j < currentLine - 1; j++){
    ct += lineMaxHeightList.get(j);
   }
   ct += layoutParams.topMargin ;
   }else{
   ct = layoutParams.topMargin;
   }
  }else{//表示當前行可以繼續(xù)添加子元素
   cl = currentLineWidth + layoutParams.leftMargin;
   if(currentLine > 1){
   for(int j = 0; j < currentLine - 1; j++){
    ct += lineMaxHeightList.get(j);
   }
   ct += layoutParams.topMargin;
   }else{
   ct = layoutParams.topMargin;
   }
   currentLineWidth += childViewWidthSpace;
   if(lineMaxHeight < childViewHeightSpace){
   lineMaxHeight = childViewHeightSpace;
   }
  }
  
  cr = cl + child.getMeasuredWidth();
  cb = ct + child.getMeasuredHeight();
  
  child.layout(cl, ct, cr, cb);
  
  }
 }
 }
 
 @Override
 public LayoutParams generateLayoutParams(AttributeSet attrs) {
 return new MarginLayoutParams(getContext(), attrs);
 }
 
 public void setTags(List<String> tags){
 if(tags!= null){
  mTags.clear();
  mTags.addAll(tags);
  for(int i = 0; i < mTags.size(); i++){
  TextView tv = new TextView(getContext());
  MarginLayoutParams lp = new MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT);
  lp.setMargins(15, 15, 15, 15);
//  lp.width = MarginLayoutParams.WRAP_CONTENT;
//  lp.height = MarginLayoutParams.WRAP_CONTENT;
  tv.setLayoutParams(lp);
  tv.setBackgroundResource(R.drawable.tv_bg);
  /*
   * setPadding一定要在setBackgroundResource后面使用才有效?。?!
   * http://stackoverflow.com/questions/18327498/setting-padding-for-textview-not-working
   */
  tv.setPadding(15, 15, 15, 15);
  tv.setTextColor(Color.WHITE);
  
  tv.setText(mTags.get(i));
  
  tv.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
   if(listener != null){
    listener.onClick(v);
   }
   }
  });
  
  addView(tv);
  }
  requestLayout();
 }
 }
 
 private OnTagItemClickListener listener;
 public interface OnTagItemClickListener{
 public void onClick(View v);
 }
 public void setOnTagItemClickListener(OnTagItemClickListener l){
 listener = l;
 }

}

MainActivity:

public class MainActivity extends Activity {
 
 private DynamicTagFlowLayout dynamicTagFlowLayout;
 
 List<String> tags = new ArrayList<String>();

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_dynamic_tagflowlayout);
 
 dynamicTagFlowLayout = (DynamicTagFlowLayout) findViewById(R.id.dynamic_tag);
 dynamicTagFlowLayout.setOnTagItemClickListener(new OnTagItemClickListener() {
  @Override
  public void onClick(View v) {
  TextView tv = (TextView) v;
  Toast.makeText(MainActivity.this, tv.getText().toString(), Toast.LENGTH_SHORT).show();
  }
 });
 
 initData();
 dynamicTagFlowLayout.setTags(tags);
 }

 private void initData() {
 tags.add("陽哥你好!");
 tags.add("Android開發(fā)");
 tags.add("新聞熱點");
 tags.add("熱水進宿舍啦!");
 tags.add("I love you");
 tags.add("成都妹子");
 tags.add("新余妹子");
 tags.add("仙女湖");
 tags.add("創(chuàng)新工廠");
 tags.add("孵化園");
 tags.add("神州100發(fā)射");
 tags.add("有毒疫苗");
 tags.add("頂你陽哥陽哥");
 tags.add("Hello World");
 tags.add("閑逛的螞蟻");
 tags.add("閑逛的螞蟻");
 tags.add("閑逛的螞蟻");
 tags.add("閑逛的螞蟻");
 tags.add("閑逛的螞蟻");
 tags.add("閑逛的螞蟻");
 }

}

源碼下載:Android流式標簽可動態(tài)添加FlowLayout  

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • android開發(fā)教程之實現(xiàn)toast工具類

    android開發(fā)教程之實現(xiàn)toast工具類

    這篇文章主要介紹了android開發(fā)中需要的toast工具類,需要的朋友可以參考下
    2014-05-05
  • Flutter路由守衛(wèi)攔截的實現(xiàn)

    Flutter路由守衛(wèi)攔截的實現(xiàn)

    路由守衛(wèi)攔截最常見的應(yīng)用場景就是對用戶數(shù)據(jù)權(quán)限的校驗,本文主要介紹了Flutter路由守衛(wèi)攔截的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 給Android初學者的Gradle知識普及

    給Android初學者的Gradle知識普及

    剛學 Android 不久,對 Gradle 不懂,看了很多資料依然一知半解,很多人都這樣覺得,表示同感,下面小編來給大家講講 Gradle相關(guān)知識,需要的朋友跟隨小編一起來學習一下
    2018-09-09
  • Android 通過cmake的方式接入opencv的方法步驟

    Android 通過cmake的方式接入opencv的方法步驟

    這篇文章主要介紹了Android 通過cmake的方式接入opencv的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • Android二級緩存加載圖片實現(xiàn)照片墻功能

    Android二級緩存加載圖片實現(xiàn)照片墻功能

    這篇文章主要為大家詳細介紹了Android二級緩存加載圖片實現(xiàn)照片墻功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android開發(fā)之判斷有無虛擬按鍵(導(dǎo)航欄)的實例

    Android開發(fā)之判斷有無虛擬按鍵(導(dǎo)航欄)的實例

    下面小編就為大家分享一篇Android開發(fā)之判斷有無虛擬按鍵(導(dǎo)航欄)的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android添加自定義下拉刷新布局阻尼滑動懸停彈動畫效果

    Android添加自定義下拉刷新布局阻尼滑動懸停彈動畫效果

    這篇文章主要為大家介紹了Android添加自定義下拉刷新布局阻尼滑動懸停彈動畫效果詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • android實現(xiàn)簡單的矩形裁剪框

    android實現(xiàn)簡單的矩形裁剪框

    這篇文章主要為大家詳細介紹了android實現(xiàn)簡單的矩形裁剪框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 實例講解Android Fragment的兩種使用方法

    實例講解Android Fragment的兩種使用方法

    今天小編就為大家分享一篇關(guān)于實例講解Android Fragment的兩種使用方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Android Studio / IDEA kotlin 顯示 var 真實類型操作

    Android Studio / IDEA kotlin 顯示 var 真實類型操作

    這篇文章主要介紹了Android Studio / IDEA kotlin 顯示 var 真實類型操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08

最新評論