fe97db514b1218a0d1fdd0a910354dd8aec75c21.svn-base 7.3 KB

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