android搜索热词(热门标签)流式布局的实现
来源:互联网 发布:淘宝中国造 编辑:程序博客网 时间:2024/05/21 07:55
先看下效果图
1、流式布局实现
继承ViewGroup,重写onMeasure,onLayout方法。代码如下:
package com.example.lin.flowlayoutdemo;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;/** * Created by lin.zhou on 2015/8/12. * 流式布局 */public class YhFlowLayout extends ViewGroup { private List<Line> mLines = new ArrayList<Line>(); // 用来记录描述有多少行View private Line mCurrrenLine; // 用来记录当前已经添加到了哪一行 private int mHorizontalSpace = 10; private int mVerticalSpace = 6; public YhFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } public YhFlowLayout(Context context) { super(context); } public void setSpace(int horizontalSpace, int verticalSpace) { this.mHorizontalSpace = horizontalSpace; this.mVerticalSpace = verticalSpace; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //清空 mLines.clear(); mCurrrenLine = null; int layoutWidth = MeasureSpec.getSize(widthMeasureSpec); // 获取行最大的宽度 int maxLineWidth = layoutWidth - getPaddingLeft() - getPaddingRight(); //测量孩子 int count = getChildCount(); for (int i = 0; i < count; i++) { View v = getChildAt(i); //如果孩子不可见 if (v.getVisibility() == GONE) { continue; } measureChild(v, widthMeasureSpec, heightMeasureSpec); // 往lines添加孩子 if (mCurrrenLine == null) { // 说明还没有开始添加孩子 mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace); // 添加到 Lines中 mLines.add(mCurrrenLine); // 行中一个孩子都没有 mCurrrenLine.addView(v); } else { // 行中有孩子了 Boolean canAdd = mCurrrenLine.canAdd(v); if (canAdd) { mCurrrenLine.addView(v); } else { //装不下,换行 mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace); mLines.add(mCurrrenLine); // 将view添加到line mCurrrenLine.addView(v); } } } // 设置自己的宽度和高度 int measuredWidth = layoutWidth; float allHeight = 0; for (int i = 0; i < mLines.size(); i++) { float mHeigth = mLines.get(i).mHeigth; // 加行高 allHeight += mHeigth; // 加间距 if (i != 0) { allHeight += mVerticalSpace; } } int measuredHeight = (int) (allHeight + getPaddingTop() + getPaddingBottom() + 0.5f); setMeasuredDimension(measuredWidth, measuredHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // 给Child 布局---> 给Line布局 int paddingLeft = getPaddingLeft(); int offsetTop = getPaddingTop(); for (int i = 0; i < mLines.size(); i++) { Line line = mLines.get(i); // 给行布局 line.layout(paddingLeft, offsetTop); offsetTop += line.mHeigth + mVerticalSpace; } } class Line { // 属性 private List<View> mViews = new ArrayList<View>(); // 用来记录每一行有几个View private float mMaxWidth; // 行最大的宽度 private float mUsedWidth; // 已经使用了多少宽度 private float mHeigth; // 行的高度 private float mMarginLeft; private float mMarginRight; private float mMarginTop; private float mMarginBottom; private float mHorizontalSpace; // View和view之间的水平间距 // 构造 public Line(int maxWidth, int horizontalSpace) { this.mMaxWidth = maxWidth; this.mHorizontalSpace = horizontalSpace; } // 方法 /** * 添加view,记录属性的变化 * * @param view */ public void addView(View view) { // 加载View的方法 int size = mViews.size(); int viewWidth = view.getMeasuredWidth(); int viewHeight = view.getMeasuredHeight(); // 计算宽和高 if (size == 0) { // 说还没有添加View if (viewWidth > mMaxWidth) { mUsedWidth = mMaxWidth; } else { mUsedWidth = viewWidth; } mHeigth = viewHeight; } else { // 多个view的情况 mUsedWidth += viewWidth + mHorizontalSpace; mHeigth = mHeigth < viewHeight ? viewHeight : mHeigth; } // 将View记录到集合中 mViews.add(view); } /** * 用来判断是否可以将View添加到line中 * * @param view * @return */ public boolean canAdd(View view) { // 判断是否能添加View int size = mViews.size(); if (size == 0) { return true; } int viewWidth = view.getMeasuredWidth(); // 预计使用的宽度 float planWidth = mUsedWidth + mHorizontalSpace + viewWidth; if (planWidth > mMaxWidth) { // 加不进去 return false; } return true; } /** * 给孩子布局 * * @param offsetLeft * @param offsetTop */ public void layout(int offsetLeft, int offsetTop) { // 给孩子布局 int currentLeft = offsetLeft; int size = mViews.size(); // 判断已经使用的宽度是否小于最大的宽度 float extra = 0; float widthAvg = 0; if (mMaxWidth > mUsedWidth) { extra = mMaxWidth - mUsedWidth; widthAvg = extra / size; } for (int i = 0; i < size; i++) { View view = mViews.get(i); int viewWidth = view.getMeasuredWidth(); int viewHeight = view.getMeasuredHeight(); // 判断是否有富余 if (widthAvg != 0) { // 改变宽度 int newWidth = (int) (viewWidth + widthAvg + 0.5f); int widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY); int heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY); view.measure(widthMeasureSpec, heightMeasureSpec); viewWidth = view.getMeasuredWidth(); viewHeight = view.getMeasuredHeight(); } // 布局 int left = currentLeft; int top = (int) (offsetTop + (mHeigth - viewHeight) / 2 + 0.5f); // int top = offsetTop; int right = left + viewWidth; int bottom = top + viewHeight; view.layout(left, top, right, bottom); currentLeft += viewWidth + mHorizontalSpace; } } }}
- 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
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 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
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
2、Demo演示
布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <com.example.lin.flowlayoutdemo.YhFlowLayout android:id="@+id/flowlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp"> </com.example.lin.flowlayoutdemo.YhFlowLayout></RelativeLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
下面根据需求设置一些流失布局中标签的属性:
private void displayUI() { for (int i = 0; i < mDatas.size(); i++) { final String data = mDatas.get(i); TextView tv = new TextView(this); tv.setText(data); tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); tv.setGravity(Gravity.CENTER); int paddingy = DisplayUtils.dp2Px(this, 7); int paddingx = DisplayUtils.dp2Px(this, 6); tv.setPadding(paddingx, paddingy, paddingx, paddingy); tv.setClickable(false); int shape = GradientDrawable.RECTANGLE; int radius = DisplayUtils.dp2Px(this, 4); int strokeWeight = DisplayUtils.dp2Px(this, 1); int stokeColor = getResources().getColor(R.color.text_color_gray); int stokeColor2 = getResources().getColor(R.color.green); GradientDrawable normalBg = DrawableUtils.getShape(shape, radius, strokeWeight, stokeColor, Color.WHITE); GradientDrawable pressedBg = DrawableUtils.getShape(shape, radius, strokeWeight, stokeColor2, getResources().getColor(R.color.green)); StateListDrawable selector = DrawableUtils.getSelector(normalBg, pressedBg); tv.setBackgroundDrawable(selector); ColorStateList colorStateList = DrawableUtils.getColorSelector(getResources().getColor(R.color.text_color_gray), getResources().getColor(R.color.white)); tv.setTextColor(colorStateList); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); flowLayout.addView(tv); } }
- 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
- 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
如果需要设置viewgroup的间距
flowLayout = (YhFlowLayout)findViewById(R.id.flowlayout); flowLayout.setSpace(DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5)); flowLayout.setPadding(DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5), DisplayUtils.dp2Px(this, 5));
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
ok,现在好看多了。
3、下面贴demo的下载地址
http://download.csdn.net/detail/zhoulin541/9574989
0 0
- android搜索热词(热门标签)流式布局的实现
- android搜索热词(热门标签)流式布局的实现
- Android 搜索界面提示语 根据不同字的个数实现不规则的 弹幕效果 流式布局,热门标签
- Android中常见的热门标签的流式布局的实现——云标签
- Android 实现FlowLayout流式布局(类似热门标签)
- Android 实现FlowLayout流式布局(类似热门标签)
- 热门标签流式布局的实现--防网易云音乐热门标签
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中常见的热门标签的流式布局的实现
- Android中Robolectric的使用
- 从C到C++的升级之函数升级
- iOS 检测网络状态
- 1079. Total Sales of Supply Chain (25)
- MySQL--数据备份还原以及主从复制
- android搜索热词(热门标签)流式布局的实现
- 三、qml调用Q_INVOKABLE方法
- java 利用jsp打印html页面
- Android aidl问题汇总
- ES6 常用API详解
- USACO 2010 Feb Silver 3.Chocolate Eating 吃巧克力
- Not found org.springframework.http.converter.json.MappingJacksonHttpMessageConve配置文件中报错
- 图解项目管理【基础】
- 数据结构实验:连通分量个数