9cc34a0d7ad6f9ff274673569735bc66d8052bb8.svn-base 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package eVVM.apk.widget;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.util.AttributeSet;
  5. import android.util.Log;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.TextView;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import eVVM.apk.R;
  13. public class LineBreakLayout extends ViewGroup {
  14. private final static String TAG = "LineBreakLayout";
  15. /**
  16. * 所有标签
  17. */
  18. private List<String> lables;
  19. private List<String> lablesid;
  20. /**
  21. * 选中标签
  22. */
  23. private List<String> lableSelected = new ArrayList<>();
  24. private List<String> lableSelectedId = new ArrayList<>();
  25. //自定义属性
  26. private int LEFT_RIGHT_SPACE; //dip
  27. private int ROW_SPACE;
  28. public LineBreakLayout(Context context) {
  29. this(context, null);
  30. }
  31. public LineBreakLayout(Context context, AttributeSet attrs) {
  32. this(context, attrs, 0);
  33. }
  34. public LineBreakLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  35. super(context, attrs, defStyleAttr);
  36. TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LineBreakLayout);
  37. LEFT_RIGHT_SPACE = ta.getDimensionPixelSize(R.styleable.LineBreakLayout_leftAndRightSpace, 10);
  38. ROW_SPACE = ta.getDimensionPixelSize(R.styleable.LineBreakLayout_rowSpace, 10);
  39. ta.recycle(); //回收
  40. // ROW_SPACE=20 LEFT_RIGHT_SPACE=40
  41. Log.v(TAG, "ROW_SPACE=" + ROW_SPACE + " LEFT_RIGHT_SPACE=" + LEFT_RIGHT_SPACE);
  42. }
  43. /**
  44. * 添加标签
  45. *
  46. * @param lables 标签集合
  47. * @param add 是否追加
  48. */
  49. public void setLables(final List<String> lables, boolean add, final List<String> ids) {
  50. if (this.lables == null) {
  51. this.lables = new ArrayList<>();
  52. this.lablesid = new ArrayList<>();
  53. }
  54. if (add) {
  55. this.lables.addAll(lables);
  56. this.lablesid.addAll(ids);
  57. } else {
  58. this.lables.clear();
  59. this.lables = lables;
  60. this.lablesid.clear();
  61. this.lablesid = ids;
  62. }
  63. if (lables != null && lables.size() > 0) {
  64. LayoutInflater inflater = LayoutInflater.from(getContext());
  65. //获取标签布局
  66. for (int i = 0; i < lables.size(); i++) {
  67. final TextView tv = (TextView) inflater.inflate(R.layout.likes_item_lable, null);
  68. tv.setText(lables.get(i));
  69. //设置选中效果
  70. if (lableSelected.contains(lables.get(i))) {
  71. //选中
  72. tv.setSelected(true);
  73. tv.setTextColor(getResources().getColor(R.color.white));
  74. } else {
  75. //未选中
  76. tv.setSelected(false);
  77. tv.setTextColor(getResources().getColor(R.color.black));
  78. }
  79. //点击标签后,重置选中效果
  80. final int finalI = i;
  81. tv.setOnClickListener(new OnClickListener() {
  82. @Override
  83. public void onClick(View v) {
  84. tv.setSelected(tv.isSelected() ? false : true);
  85. if (tv.isSelected()) {
  86. tv.setTextColor(getResources().getColor(R.color.white));
  87. //将选中的标签加入到lableSelected中
  88. lableSelected.add(lables.get(finalI));
  89. lableSelectedId.add(ids.get(finalI));
  90. } else {
  91. tv.setTextColor(getResources().getColor(R.color.black));
  92. lableSelected.remove(lables.get(finalI));
  93. lableSelectedId.remove(ids.get(finalI));
  94. }
  95. }
  96. });
  97. //将标签添加到容器中
  98. addView(tv);
  99. }
  100. /* for (final String lable : lables) {
  101. //获取标签布局
  102. final TextView tv = (TextView) inflater.inflate(R.layout.likes_item_lable, null);
  103. tv.setText(lable);
  104. //设置选中效果
  105. if (lableSelected.contains(lable)) {
  106. //选中
  107. tv.setSelected(true);
  108. tv.setTextColor(getResources().getColor(R.color.white));
  109. } else {
  110. //未选中
  111. tv.setSelected(false);
  112. tv.setTextColor(getResources().getColor(R.color.black));
  113. }
  114. //点击标签后,重置选中效果
  115. tv.setOnClickListener(new OnClickListener() {
  116. @Override
  117. public void onClick(View v) {
  118. tv.setSelected(tv.isSelected() ? false : true);
  119. if (tv.isSelected()) {
  120. tv.setTextColor(getResources().getColor(R.color.white));
  121. //将选中的标签加入到lableSelected中
  122. lableSelected.add(lable);
  123. } else {
  124. tv.setTextColor(getResources().getColor(R.color.black));
  125. lableSelected.remove(lable);
  126. }
  127. }
  128. });
  129. //将标签添加到容器中
  130. addView(tv);
  131. }*/
  132. }
  133. }
  134. /**
  135. * 获取选中标签
  136. */
  137. public List<String> getSelectedLables() {
  138. return lableSelected;
  139. }
  140. /**
  141. * 获取选中标签id
  142. */
  143. public List<String> getSelectedLablesid() {
  144. return lableSelectedId;
  145. }
  146. @Override
  147. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  148. //为所有的标签childView计算宽和高
  149. measureChildren(widthMeasureSpec, heightMeasureSpec);
  150. //获取高的模式
  151. int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  152. //建议的高度
  153. int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  154. //布局的宽度采用建议宽度(match_parent或者size),如果设置wrap_content也是match_parent的效果
  155. int width = MeasureSpec.getSize(widthMeasureSpec);
  156. int height;
  157. if (heightMode == MeasureSpec.EXACTLY) {
  158. //如果高度模式为EXACTLY(match_perent或者size),则使用建议高度
  159. height = heightSize;
  160. } else {
  161. //其他情况下(AT_MOST、UNSPECIFIED)需要计算计算高度
  162. int childCount = getChildCount();
  163. if (childCount <= 0) {
  164. height = 0; //没有标签时,高度为0
  165. } else {
  166. int row = 1; // 标签行数
  167. int widthSpace = width;// 当前行右侧剩余的宽度
  168. for (int i = 0; i < childCount; i++) {
  169. View view = getChildAt(i);
  170. //获取标签宽度
  171. int childW = view.getMeasuredWidth();
  172. Log.v(TAG, "标签宽度:" + childW + " 行数:" + row + " 剩余宽度:" + widthSpace);
  173. if (widthSpace >= childW) {
  174. //如果剩余的宽度大于此标签的宽度,那就将此标签放到本行
  175. widthSpace -= childW;
  176. } else {
  177. row++; //增加一行
  178. //如果剩余的宽度不能摆放此标签,那就将此标签放入一行
  179. widthSpace = width - childW;
  180. }
  181. //减去标签左右间距
  182. widthSpace -= LEFT_RIGHT_SPACE;
  183. }
  184. //由于每个标签的高度是相同的,所以直接获取第一个标签的高度即可
  185. int childH = getChildAt(0).getMeasuredHeight();
  186. //最终布局的高度=标签高度*行数+行距*(行数-1)
  187. height = (childH * row) + ROW_SPACE * (row - 1);
  188. Log.v(TAG, "总高度:" + height + " 行数:" + row + " 标签高度:" + childH);
  189. }
  190. }
  191. //设置测量宽度和测量高度
  192. setMeasuredDimension(width, height);
  193. }
  194. @Override
  195. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  196. int row = 0;
  197. int right = 0; // 标签相对于布局的右侧位置
  198. int botom; // 标签相对于布局的底部位置
  199. for (int i = 0; i < getChildCount(); i++) {
  200. View childView = getChildAt(i);
  201. int childW = childView.getMeasuredWidth();
  202. int childH = childView.getMeasuredHeight();
  203. //右侧位置=本行已经占有的位置+当前标签的宽度
  204. right += childW;
  205. //底部位置=已经摆放的行数*(标签高度+行距)+当前标签高度
  206. botom = row * (childH + ROW_SPACE) + childH;
  207. // 如果右侧位置已经超出布局右边缘,跳到下一行
  208. // if it can't drawing on a same line , skip to next line
  209. if (right > (r - LEFT_RIGHT_SPACE)) {
  210. row++;
  211. right = childW;
  212. botom = row * (childH + ROW_SPACE) + childH;
  213. }
  214. Log.d(TAG, "left = " + (right - childW) + " top = " + (botom - childH) +
  215. " right = " + right + " botom = " + botom);
  216. childView.layout(right - childW, botom - childH, right, botom);
  217. right += LEFT_RIGHT_SPACE;
  218. }
  219. }
  220. }