androi自定义自动换行的View(类似网页的标签Tag)
看来只有礼拜天才有时间写点博客啊,平时只能埋头苦干了。今天在公司加班,遇到一个需求,就是自动换行的TextView,有点像网页的tag标签,点击一下,就自动加上去了,不过这个是根据后台拿来的数据来显示多少个View,在网上找找,看见了许多,我自己也封装写一个吧,以便以后需要...开工
|
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
|
package com.woyou.ui.component;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.citaq.ideliver.R;/** * 自动换行的View * * @author shenzhou 2015年1月11日 */public class WordWrapView extends ViewGroup { private static final int PADDING_HOR = 10;// 水平方向padding private static final int PADDING_VERTICAL = 15;// 垂直方向padding private static final int SIDE_MARGIN = 10;// 左右间距 private static final int TEXT_MARGIN = 10; public WordWrapView(Context context) { super(context); } public WordWrapView(Context context, AttributeSet attrs) { super(context, attrs); } public WordWrapView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int autualWidth = r - l; int x = SIDE_MARGIN;// 横坐标开始 int y = 0;// 纵坐标开始 int rows = 1; for (int i = 0; i < childCount; i++) { View view = getChildAt(i); view.setBackgroundResource(R.drawable.shopdetail_keytag_bg); int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); x += width + TEXT_MARGIN; if (x > autualWidth) { x = width + SIDE_MARGIN; rows++; } y = rows * (height + TEXT_MARGIN); if (i == 0) { view.layout(x - width - TEXT_MARGIN, y - height, x - TEXT_MARGIN, y); } else { view.layout(x - width, y - height, x, y); } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int x = 0;// 横坐标 int y = 0;// 纵坐标 int rows = 1;// 总行数 int specWidth = MeasureSpec.getSize(widthMeasureSpec); int actualWidth = specWidth - SIDE_MARGIN * 2;// 实际宽度 int childCount = getChildCount(); for (int index = 0; index < childCount; index++) { View child = (TextView) getChildAt(index); child.setPadding(PADDING_HOR, PADDING_VERTICAL, PADDING_HOR, PADDING_VERTICAL); child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); x += width + TEXT_MARGIN; if (x > actualWidth) {// 换行 x = width; rows++; } y = rows * (height + TEXT_MARGIN); } setMeasuredDimension(actualWidth, y); }} |
具体使用:
我的项目的布局文件太长了,我就说了
|
1
|
<com.woyou.ui.component.wordwrapview style="@style/shopDetailTextStyle" android:id="@+id/shopdetail_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingleft="@dimen/dp20" android:paddingright="@dimen/dp20" android:paddingtop="@dimen/dp10"></com.woyou.ui.component.wordwrapview> |
把这段布局文件加到你要把文字自动换行的地方。java文件中的使用:
|
1
2
3
4
5
6
7
8
9
10
11
|
if ( !TextUtils.isEmpty(shopDetail.getInfo()) ) { infoLin.setVisibility(View.VISIBLE); //店铺关键字 String key = shopDetail.getKey(); strs = key.split("\\|"); for (int i = 0; i < strs.length; i++) { TextView textview = new TextView(mActivity); textview.setText(strs[i]); wordWrapView.addView(textview); } LogUtil.i(TAG, "tags:" + strs.toString()); |
前面还有找到控件什么的,我相信大家都是知道的。这只是核心代码,效果图如下:

<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKjwvcD4KPHA+KioqKioqKioqKioqKioqKioqKioqKr3pydzB7c3i0rvW1re9t6ijrMrHxLO49rTzyfHQtLXEo6yyu7n9w7u34tewo6y5qbTzvNKyzr+8KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio8L3A+CjxwPioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;"> /** 标签之间的间距 px */ private final int itemMargins = (int) getContext().getResources().getDimension(R.dimen.dp15); /** 标签的行间距 px */ private final int lineMargins = (int) getContext().getResources().getDimension(R.dimen.dp10);
|
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
|
/** * 加载店铺关键字 * @param tags */ private void loadShopKeys (String[] tags) { if ( tags == null ) return; final int containerWidth = container.getMeasuredWidth() - container.getPaddingRight() - container.getPaddingLeft(); final LayoutInflater inflater = mActivity.getLayoutInflater(); /** 用来测量字符的宽度 */ final Paint paint = new Paint(); final TextView textView = (TextView) inflater.inflate(R.layout.item_textviewtag_lv, null); final int itemPadding = textView.getCompoundPaddingLeft() + textView.getCompoundPaddingRight(); final LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); tvParams.setMargins(0, 0, itemMargins, 0); paint.setTextSize(textView.getTextSize()); LinearLayout layout = new LinearLayout(getContext()); layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); layout.setOrientation(LinearLayout.HORIZONTAL); container.addView(layout); final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); params.setMargins(0, lineMargins, 0, 0); /** 一行剩下的空间 **/ int remainWidth = containerWidth; for (int i = 0; i < tags.length; ++i) { final String text = tags[i]; final float itemWidth = paint.measureText(text) + itemPadding; if (remainWidth > itemWidth) { addItemView(inflater, layout, tvParams, text); } else { resetTextViewMarginsRight(layout); layout = new LinearLayout(getContext()); layout.setLayoutParams(params); layout.setOrientation(LinearLayout.HORIZONTAL); /** 将前面那一个textview加入新的一行 */ addItemView(inflater, layout, tvParams, text); container.addView(layout); remainWidth = containerWidth; } remainWidth = (int) (remainWidth - itemWidth + 0.5f) - itemMargins; } resetTextViewMarginsRight(layout); } /***************** 将每行最后一个textview的MarginsRight去掉 *********************************/ private void resetTextViewMarginsRight(ViewGroup viewGroup) { final TextView tempTx = (TextView) viewGroup.getChildAt(viewGroup.getChildCount() - 1); tempTx.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } private void addItemView(LayoutInflater inflater, ViewGroup viewGroup, android.widget.LinearLayout.LayoutParams tvParams, String text) { final TextView itemTx = (TextView) inflater.inflate(R.layout.item_textviewtag_lv, null); itemTx.setText(text); viewGroup.addView(itemTx, tvParams); } |
推推族,免费得门票,游景区:www.tuituizu.com
结伴旅游,一个免费的交友网站:www.jieberu.com
androi自定义自动换行的View(类似网页的标签Tag)的更多相关文章
- C#微信公众号开发 -- (七)自定义菜单事件之VIEW及网页(OAuth2.0)授权
通俗来讲VIEW其实就是我们在C#中常用的a标签,可以直接在自定义菜单URL的属性里面写上需要跳转的链接,也即为单纯的跳转. 但更多的情况下,我们是想通过VIEW来进入指定的页面并进行操作. 举一个简 ...
- 自定义控制器的View(loadView)及其注意点
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 贝塞尔曲线:原理、自定义贝塞尔曲线View、使用!!!
一.原理 转自:http://www.2cto.com/kf/201401/275838.html Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation Pr ...
- android 开发 View _14 MotionEvent和事件处理详解,与实践自定义滑动条View
转载https://blog.csdn.net/huaxun66/article/details/52352469 MotionEvent MotionEvent对象是与用户触摸相关的时间序列,该序列 ...
- android显示通知栏Notification以及自定义Notification的View
遇到的最大的问题是监听不到用户清除通知栏的广播.所以是不能监听到的. 自定义通知栏的View,然后service运行时更改notification的信息. /** * Show a notificat ...
- 浅析网页meta标签中X-UA-Compatible属性的使用
今天有一个做开发的朋友突然问你知道很多网站上面加入的X-UA-Compatible属性的意义么?其实这个在以前还专门花了一点时间来验证我自己的想法,结果也确实如自己所预想的那样,八九不离十,当然有一点 ...
- php实现网页HTML标签补全方法
如果你的网页内容的html标签显示不全,有些表格标签不完整而导致页面混乱,或者把你的内容之外的局部html页面给包含进去了,我们可以写个函数方法来补全html标签以及过滤掉无用的html标签. php ...
- 一、变量.二、过滤器(filter).三、标签(tag).四、条件分支tag.五、迭代器tag.六、自定义过滤器与标签.七、全系统过滤器(了解)
一.变量 ''' 1.视图函数可以通过两种方式将变量传递给模板页面 -- render(request, 'test_page.html', {'变量key1': '变量值1', ..., '变量ke ...
- JSTL核心标签库——重定向标签、URL处理标签、网页导入标签
<c:redirect>重定向标签 相当于HttpServletResponse的sendRedirect()方法. <%@page contentType="text/h ...
随机推荐
- 通过U盘或CD/DVD装centos7,出现“dracut-initqueue timeout..."解决办法
1.在用CD/DVD挂载centos7镜像安装系统时,出现“dracut-initqueue timeout...", :/# cd dev :/# ls 2.这是因为安装程序未能找到安装文 ...
- [转帖]Marvell第二代ARM处理器ThunderX2解析
Marvell第二代ARM处理器ThunderX2解析 https://www.cnbeta.com/articles/tech/853137.htm 长久以来,服务器数据中心市场一直被x86 CPU ...
- JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别
JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别 :https://blog.csdn.net/hyupeng1006/a ...
- opencv学习之显示图像-imshow函数
序 上一篇opencv学习之读取图像-imread函数介绍完opencv读取图片函数imread,这次来介绍与它对应的图像显示函数imshow. imshow函数 imshow函数功能 imshow的 ...
- 剑指offer-最小的K个数-时间效率-排序-python
题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 这就是排序题(将结果的最小K值输出) # -*- coding ...
- 手把手教你上传文件到GitHub上(已获取ssh密钥)
如何提交一个文件到GitHub(已经生成ssh key) 1.新建一个文件夹,当作本地仓库 2.初始化仓库 $git init 3.将想要上传的东西复制到仓库中 4.将文件提交到暂存区 $git ad ...
- 4种vue当中的指令和它的用法
1.v-if:判断是否隐藏 2.v-for:数据循环 3.v-bind:class:绑定一个属性 4.v-model:实现数据双向绑定 这里重点说明一个v-if和v-show的区别: 共同点:都是通过 ...
- 可以提升幸福感的js小技巧(下)
4.数字 4.1 不同进制表示法 ES6中新增了不同进制的书写格式,在后台传参的时候要注意这一点. 29 // 10进制 035 // 8进制29 原来的方式 0o35 // 8进制29 ES6的方式 ...
- Scala Nothing 从官方DOC翻译
Nothing is - together with scala.Null - at the bottom of Scala's type hierarchy. Scala中的Nothing和Null ...
- vim 添加显示和行号
方法一: 1.显示当前行行号,在VI的命令模式下输入 :nu 2.显示所有行号,在VI的命令模式下输入 :set nu :set nonu 关闭 方法二: 使用vi编辑~/.vimrc文件,在该文件中 ...