Android笔记:热门标签,流式布局

简介:

一、测试效果未成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package  cn.app.meiya.aa.widget;
 
import  android.content.Context;
import  android.util.AttributeSet;
import  android.view.View;
import  android.view.ViewGroup;
 
import  java.util.ArrayList;
import  java.util.List;
 
/**
  * 类似话题标签的流式布局,测试效果无效
  * http://www.apkbus.com/android-239725-1-1.html
  * Created by lonshine on 15/7/16.
  */
public  class  TopicFlowLayout  extends  ViewGroup {
 
     //存储所有子View
     private  List<List<View>> mAllChildViews =  new  ArrayList<>();
     //每一行的高度
     private  List<Integer> mLineHeight =  new  ArrayList<>();
 
     public  TopicFlowLayout(Context context) {
         this (context,  null );
         // TODO Auto-generated constructor stub
     }
 
     public  TopicFlowLayout(Context context, AttributeSet attrs) {
         this (context, attrs,  0 );
         // TODO Auto-generated constructor stub
     }
 
     public  TopicFlowLayout(Context context, AttributeSet attrs,  int  defStyle) {
         super (context, attrs, defStyle);
         // TODO Auto-generated constructor stub
     }
 
     @Override
     protected  void  onMeasure( int  widthMeasureSpec,  int  heightMeasureSpec) {
         // TODO Auto-generated method stub
 
         //父控件传进来的宽度和高度以及对应的测量模式
         int  sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
         int  modeWidth = MeasureSpec.getMode(widthMeasureSpec);
         int  sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
         int  modeHeight = MeasureSpec.getMode(heightMeasureSpec);
 
         //如果当前ViewGroup的宽高为wrap_content的情况
         int  width =  0 ; //自己测量的 宽度
         int  height =  0 ; //自己测量的高度
         //记录每一行的宽度和高度
         int  lineWidth =  0 ;
         int  lineHeight =  0 ;
 
         //获取子view的个数
         int  childCount = getChildCount();
         for  ( int  i =  0 ; i < childCount; i++) {
             View child = getChildAt(i);
             //测量子View的宽和高
             measureChild(child, widthMeasureSpec, heightMeasureSpec);
             //得到LayoutParams
             MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
             //子View占据的宽度
             int  childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
             //子View占据的高度
             int  childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
             //换行时候
             if  (lineWidth + childWidth > sizeWidth) {
                 //对比得到最大的宽度
                 width = Math.max(width, lineWidth);
                 //重置lineWidth
                 lineWidth = childWidth;
                 //记录行高
                 height += lineHeight;
                 lineHeight = childHeight;
             else  { //不换行情况
                 //叠加行宽
                 lineWidth += childWidth;
                 //得到最大行高
                 lineHeight = Math.max(lineHeight, childHeight);
             }
             //处理最后一个子View的情况
             if  (i == childCount -  1 ) {
                 width = Math.max(width, lineWidth);
                 height += lineHeight;
             }
         }
         //wrap_content
         setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,
                 modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);
         super .onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
     @Override
     protected  void  onLayout( boolean  changed,  int  l,  int  t,  int  r,  int  b) {
         // TODO Auto-generated method stub
         mAllChildViews.clear();
         mLineHeight.clear();
         //获取当前ViewGroup的宽度
         int  width = getWidth();
 
         int  lineWidth =  0 ;
         int  lineHeight =  0 ;
         //记录当前行的view
         List<View> lineViews =  new  ArrayList<View>();
         int  childCount = getChildCount();
         for  ( int  i =  0 ; i < childCount; i++) {
             View child = getChildAt(i);
             MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
             int  childWidth = child.getMeasuredWidth();
             int  childHeight = child.getMeasuredHeight();
 
             //如果需要换行
             if  (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width) {
                 //记录LineHeight
                 mLineHeight.add(lineHeight);
                 //记录当前行的Views
                 mAllChildViews.add(lineViews);
                 //重置行的宽高
                 lineWidth =  0 ;
                 lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
                 //重置view的集合
                 lineViews =  new  ArrayList();
             }
             lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
             lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
             lineViews.add(child);
         }
         //处理最后一行
         mLineHeight.add(lineHeight);
         mAllChildViews.add(lineViews);
 
         //设置子View的位置
         int  left =  0 ;
         int  top =  0 ;
         //获取行数
         int  lineCount = mAllChildViews.size();
         for  ( int  i =  0 ; i < lineCount; i++) {
             //当前行的views和高度
             lineViews = mAllChildViews.get(i);
             lineHeight = mLineHeight.get(i);
             for  ( int  j =  0 ; j < lineViews.size(); j++) {
                 View child = lineViews.get(j);
                 //判断是否显示
                 if  (child.getVisibility() == View.GONE) {
                     continue ;
                 }
                 MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                 int  cLeft = left + lp.leftMargin;
                 int  cTop = top + lp.topMargin;
                 int  cRight = cLeft + child.getMeasuredWidth();
                 int  cBottom = cTop + child.getMeasuredHeight();
                 //进行子View进行布局
                 child.layout(cLeft, cTop, cRight, cBottom);
                 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
             }
             left =  0 ;
             top += lineHeight;
         }
 
     }
 
     /**
      * 与当前ViewGroup对应的LayoutParams
      */
     @Override
     public  LayoutParams generateLayoutParams(AttributeSet attrs) {
         // TODO Auto-generated method stub
 
         return  new  MarginLayoutParams(getContext(), attrs);
     }
 
 
}


用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<font color= "#362e2b" ><font style= "background-color:rgb(255, 255, 255)" ><font face= "Arial" ><font style= "font-size:14px" > package  com.czm.flowlayout;
  
import  android.app.Activity;
import  android.graphics.Color;
import  android.os.Bundle;
import  android.view.ViewGroup.LayoutParams;
import  android.view.ViewGroup.MarginLayoutParams;
import  android.widget.TextView;
/**
 
  * @author caizhiming
  * @created on 2015-4-13
  */
public  class  MainActivity  extends  Activity {
  
     private  String mNames[] = {
             "welcome" , "android" , "TextView" ,
             "apple" , "jamy" , "kobe bryant" ,
             "jordan" , "layout" , "viewgroup" ,
             "margin" , "padding" , "text" ,
             "name" , "type" , "search" , "logcat"
     };
     private  XCFlowLayout mFlowLayout;
     @Override
     protected  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
          
         initChildViews();
          
     }
     private  void  initChildViews() {
         // TODO Auto-generated method stub
         mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout);
         MarginLayoutParams lp =  new  MarginLayoutParams(
                 LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
         lp.leftMargin =  5 ;
         lp.rightMargin =  5 ;
         lp.topMargin =  5 ;
         lp.bottomMargin =  5 ;
         for ( int  i =  0 ; i < mNames.length; i ++){
             TextView view =  new  TextView( this );
             view.setText(mNames[i]);
             view.setTextColor(Color.WHITE);
             view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));
             mFlowLayout.addView(view,lp);
         }
     }
  
}</font></font></font></font>



二、测试可用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package  cn.app.meiya.aa.widget;
 
import  android.content.Context;
import  android.util.AttributeSet;
import  android.view.View;
import  android.view.ViewGroup;
 
/**
  * http://www.bkjia.com/Androidjc/1013458.html
  * Created by lonshine on 15/7/16.
  */
public  class  FlowLayout  extends  ViewGroup {
     private  float  mVerticalSpacing;  //每个item纵向间距
     private  float  mHorizontalSpacing;  //每个item横向间距
 
     public  FlowLayout(Context context) {
         super (context);
     }
     public  FlowLayout(Context context, AttributeSet attrs) {
         super (context, attrs);
     }
     public  void  setHorizontalSpacing( float  pixelSize) {
         mHorizontalSpacing = pixelSize;
     }
     public  void  setVerticalSpacing( float  pixelSize) {
         mVerticalSpacing = pixelSize;
     }
     @Override
     protected  void  onMeasure( int  widthMeasureSpec,  int  heightMeasureSpec) {
         int  selfWidth = resolveSize( 0 , widthMeasureSpec);
 
         int  paddingLeft = getPaddingLeft();
         int  paddingTop = getPaddingTop();
         int  paddingRight = getPaddingRight();
         int  paddingBottom = getPaddingBottom();
 
         int  childLeft = paddingLeft;
         int  childTop = paddingTop;
         int  lineHeight =  0 ;
 
         //通过计算每一个子控件的高度,得到自己的高度
         for  ( int  i =  0 , childCount = getChildCount(); i < childCount; ++i) {
             View childView = getChildAt(i);
             LayoutParams childLayoutParams = childView.getLayoutParams();
             childView.measure(
                     getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,
                             childLayoutParams.width),
                     getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,
                             childLayoutParams.height));
             int  childWidth = childView.getMeasuredWidth();
             int  childHeight = childView.getMeasuredHeight();
 
             lineHeight = Math.max(childHeight, lineHeight);
 
             if  (childLeft + childWidth + paddingRight > selfWidth) {
                 childLeft = paddingLeft;
                 childTop += mVerticalSpacing + lineHeight;
                 lineHeight = childHeight;
             else  {
                 childLeft += childWidth + mHorizontalSpacing;
             }
         }
 
         int  wantedHeight = childTop + lineHeight + paddingBottom;
         setMeasuredDimension(selfWidth, resolveSize(wantedHeight, heightMeasureSpec));
     }
 
     @Override
     protected  void  onLayout( boolean  changed,  int  l,  int  t,  int  r,  int  b) {
         int  myWidth = r - l;
 
         int  paddingLeft = getPaddingLeft();
         int  paddingTop = getPaddingTop();
         int  paddingRight = getPaddingRight();
 
         int  childLeft = paddingLeft;
         int  childTop = paddingTop;
 
         int  lineHeight =  0 ;
 
         //根据子控件的宽高,计算子控件应该出现的位置。
         for  ( int  i =  0 , childCount = getChildCount(); i < childCount; ++i) {
             View childView = getChildAt(i);
 
             if  (childView.getVisibility() == View.GONE) {
                 continue ;
             }
 
             int  childWidth = childView.getMeasuredWidth();
             int  childHeight = childView.getMeasuredHeight();
 
             lineHeight = Math.max(childHeight, lineHeight);
 
             if  (childLeft + childWidth + paddingRight > myWidth) {
                 childLeft = paddingLeft;
                 childTop += mVerticalSpacing + lineHeight;
                 lineHeight = childHeight;
             }
             childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
             childLeft += childWidth + mHorizontalSpacing;
         }
     }
}




本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1675221,如需转载请自行联系原作者

目录
相关文章
|
1天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
51 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
1天前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
49 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
1天前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
28 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
1天前
|
存储 Java API
Android系统 文件访问权限笔记
Android系统 文件访问权限笔记
65 1
|
1天前
|
XML Java Android开发
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
Android Studio App开发中工具栏Toolbar、溢出菜单OverflowMenu、标签布局TabLayout的讲解及实战(实现京东App的标签导航栏,附源码)
99 0
|
7月前
|
Java Android开发
[笔记]Android 学习一之转场动画+ViewPager+ListView简单Demo
[笔记]Android 学习一之转场动画+ViewPager+ListView简单Demo
|
7月前
|
Android开发
[笔记]Android开发之相机开发 Camera1、2、X
[笔记]Android开发之相机开发 Camera1、2、X
|
9月前
|
Android开发
Android 获取include标签中的控件属性并设置事件
Android 获取include标签中的控件属性并设置事件
144 0
|
编解码 Android开发
Android | 老生常谈!屏幕适配原理 & 方案总结笔记
Android | 老生常谈!屏幕适配原理 & 方案总结笔记
482 0
Android | 老生常谈!屏幕适配原理 & 方案总结笔记