开发文章

安卓仿微信添加标签效果

一、 概述

可以说微信做的用户体验太棒了,可以做到老少皆宜,给个赞,我们也同时应该告诫自己,用户体验应该向微信看齐,微信就是我们的标杆,那我们今天也来仿一仿微信添加的标签功能。只能仿着做了,真是做不到微信的那种体验。甘拜下风。

我们上篇学习了shape属性的用法,那我们今天就用shape来做下微信的标签功能。先看一下效果。

我不仅用到了shape属性,还用到了翔哥的标签布局FlowLayout跟TagFlowLayout鸿洋的博客(http://blog.csdn.net/lmj623565791)

二、效果图

效果图.gif

三 、定义shape

  • 添加标签

复制内容到剪贴板
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:shape="rectangle" >  
  4.   
  5. <corners  
  6.   android:bottomLeftRadius="30dp"  
  7.   android:bottomRightRadius="30dp"  
  8.   android:topLeftRadius="30dp"  
  9.   android:topRightRadius="30dp" />  
  10.   
  11. <stroke android:dashWidth="5dp" android:dashGap="2dp" android:width="1dp" android:color="#e0e0e0"  />  
  12.   
  13. <padding  
  14.   android:bottom="2dp"  
  15.   android:left="10dp"  
  16.   android:right="10dp"  
  17.   android:top="2dp" />  
  18. </shape>  

删除标签

复制内容到剪贴板
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:shape="rectangle">  
  4.   
  5. <corners  
  6.     android:bottomLeftRadius="30dp"  
  7.     android:bottomRightRadius="30dp"  
  8.     android:topLeftRadius="30dp"  
  9.     android:topRightRadius="30dp" />  
  10.   
  11.   
  12. <solid android:color="#00FF00" />  
  13.   
  14. <padding  
  15.     android:bottom="2dp"  
  16.     android:left="10dp"  
  17.     android:right="10dp"  
  18.     android:top="2dp" />  
  19.   
  20. </shape>   

正常标签

复制内容到剪贴板
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:shape="rectangle" >  
  4.   
  5. <corners  
  6.   android:bottomLeftRadius="30dp"  
  7.   android:bottomRightRadius="30dp"  
  8.   android:topLeftRadius="30dp"  
  9.   android:topRightRadius="30dp" />  
  10.   
  11.   
  12. <stroke  android:width="1dp" android:color="#00FF00"  />  
  13.   
  14. <padding  
  15.   android:bottom="2dp"  
  16.   android:left="10dp"  
  17.   android:right="10dp"  
  18.   android:top="2dp" />  
  19.   
  20. </shape>    

标签选中

复制内容到剪贴板
  1.    <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:shape="rectangle">  
  4.   
  5. <corners  
  6.     android:bottomLeftRadius="30dp"  
  7.     android:bottomRightRadius="30dp"  
  8.     android:topLeftRadius="30dp"  
  9.     android:topRightRadius="30dp" />  
  10.   
  11.   
  12. <stroke  
  13.     android:width="1dp"  
  14.     android:color="#00FF00" />  
  15.   
  16. <padding  
  17.     android:bottom="2dp"  
  18.     android:left="10dp"  
  19.     android:right="10dp"  
  20.     android:top="2dp" />  
  21.   
  22. </shape>     

以上是部分shape定义,大家可以下载源码自己看。

四、 思路

我们可以标签大概有以下逻辑

  • 点击上面标签删除 所有标签里面更新未选中
  • 点击所有标签的某一个 上面标签添加或者删除

五、代码

复制内容到剪贴板
  1. public class MainActivity extends AppCompatActivity {  
  2. private FlowLayout flowLayout;//上面的flowLayout  
  3. private TagFlowLayout allFlowLayout;//所有标签的TagFlowLayout  
  4. private List<String> label_list = new ArrayList<>();//上面的标签列表  
  5. private List<String> all_label_List = new ArrayList<>();//所有标签列表  
  6. final List<TextView> labels = new ArrayList<>();//存放标签  
  7. final List<Boolean> labelStates = new ArrayList<>();//存放标签状态  
  8. final Set<Integer> set = new HashSet<>();//存放选中的  
  9. private TagAdapter<String> tagAdapter;//标签适配器  
  10. private LinearLayout.LayoutParams params;  
  11. private EditText editText;  
  12.   
  13.   
  14. @Override  
  15. protected void onCreate(Bundle savedInstanceState) {  
  16.     super.onCreate(savedInstanceState);  
  17.     setContentView(R.layout.activity_main);  
  18.     initView();  
  19.     initData();  
  20.     initEdittext();  
  21.     initAllLeblLayout();  
  22. }  
  23.   
  24.   
  25. /** 
  26.  * 初始化View 
  27.  */  
  28. private void initView() {  
  29.     flowLayout = (FlowLayout) findViewById(R.id.id_flowlayout);  
  30.     allFlowLayout = (TagFlowLayout) findViewById(R.id.id_flowlayout_two);  
  31.     params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);  
  32.     params.setMargins(20202020);  
  33.     flowLayout.setOnClickListener(new View.OnClickListener() {  
  34.         @Override  
  35.         public void onClick(View view) {  
  36.             String editTextContent = editText.getText().toString();  
  37.             if (TextUtils.isEmpty(editTextContent)) {  
  38.                 tagNormal();  
  39.             } else {  
  40.                 addLabel(editText);  
  41.             }  
  42.         }  
  43.     });  
  44. }  
  45. /** 
  46.  * 初始化数据 
  47.  */  
  48. private void initData(){  
  49.     //初始化上面标签  
  50.     label_list.add("同事");  
  51.     label_list.add("亲人");  
  52.     label_list.add("同学");  
  53.     label_list.add("朋友");  
  54.     label_list.add("知己");  
  55.     //初始化下面标签列表  
  56.     all_label_List.addAll(label_list);  
  57.     all_label_List.add("异性朋友");  
  58.     all_label_List.add("高中同学");  
  59.     all_label_List.add("大学同学");  
  60.     all_label_List.add("社会朋友");  
  61.   
  62.     for (int i = 0; i < label_list.size() ; i++) {  
  63.         editText = new EditText(getApplicationContext());//new 一个EditText  
  64.         editText.setText(label_list.get(i));  
  65.         addLabel(editText);//添加标签  
  66.     }  
  67.   
  68. }  
  69.   
  70. /** 
  71.  * 初始化默认的添加标签 
  72.  */  
  73. private void initEdittext(){  
  74.     editText = new EditText(getApplicationContext());  
  75.     editText.setHint("添加标签");  
  76.     //设置固定宽度  
  77.     editText.setMinEms(4);  
  78.     editText.setTextSize(12);  
  79.     //设置shape  
  80.     editText.setBackgroundResource(R.drawable.label_add);  
  81.     editText.setHintTextColor(Color.parseColor("#b4b4b4"));  
  82.     editText.setTextColor(Color.parseColor("#000000"));  
  83.     editText.setLayoutParams(params);  
  84.     //添加到layout中  
  85.     flowLayout.addView(editText);  
  86.     editText.addTextChangedListener(new TextWatcher() {  
  87.         @Override  
  88.         public void beforeTextChanged(CharSequence s, int start, int count, int after) {  
  89.   
  90.         }  
  91.   
  92.         @Override  
  93.         public void onTextChanged(CharSequence s, int start, int before, int count) {  
  94.             tagNormal();  
  95.         }  
  96.   
  97.         @Override  
  98.         public void afterTextChanged(Editable s) {  
  99.   
  100.         }  
  101.     });  
  102.   
  103. }  
  104.   
  105. /** 
  106.  * 初始化所有标签列表 
  107.  */  
  108. private void initAllLeblLayout() {  
  109.     //初始化适配器  
  110.     tagAdapter = new TagAdapter<String>(all_label_List) {  
  111.         @Override  
  112.         public View getView(FlowLayout parent, int position, String s) {  
  113.             TextView tv = (TextView) getLayoutInflater().inflate(R.layout.flag_adapter,  
  114.                     allFlowLayout, false);  
  115.             tv.setText(s);  
  116.             return tv;  
  117.         }  
  118.     };  
  119.   
  120.     allFlowLayout.setAdapter(tagAdapter);  
  121.   
  122.     //根据上面标签来判断下面的标签是否含有上面的标签  
  123.     for (int i = 0; i < label_list.size(); i++) {  
  124.         for (int j = 0; j < all_label_List.size(); j++) {  
  125.             if (label_list.get(i).equals(  
  126.                     all_label_List.get(j))) {  
  127.                 tagAdapter.setSelectedList(i);//设为选中  
  128.             }  
  129.         }  
  130.     }  
  131.     tagAdapter.notifyDataChanged();  
  132.   
  133.   
  134.     //给下面的标签添加监听  
  135.     allFlowLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener() {  
  136.         @Override  
  137.         public boolean onTagClick(View view, int position, FlowLayout parent) {  
  138.             if (labels.size() == 0) {  
  139.                 editText.setText(all_label_List.get(position));  
  140.                 addLabel(editText);  
  141.                 return false;  
  142.             }  
  143.             List<String> list = new ArrayList<>();  
  144.             for (int i = 0; i < labels.size(); i++) {  
  145.                 list.add(labels.get(i).getText().toString());  
  146.             }  
  147.             //如果上面包含点击的标签就删除  
  148.             if (list.contains(all_label_List.get(position))) {  
  149.                 for (int i = 0; i < list.size(); i++) {  
  150.                     if (all_label_List.get(position).equals(list.get(i))) {  
  151.                         flowLayout.removeView(labels.get(i));  
  152.                         labels.remove(i);  
  153.                     }  
  154.                 }  
  155.   
  156.             } else {  
  157.                 editText.setText(all_label_List.get(position));  
  158.                 addLabel(editText);  
  159.             }  
  160.   
  161.             return false;  
  162.         }  
  163.     });  
  164.   
  165.     //已经选中的监听  
  166.     allFlowLayout.setOnSelectListener(new TagFlowLayout.OnSelectListener() {  
  167.   
  168.         @Override  
  169.         public void onSelected(Set<Integer> selectPosSet) {  
  170.             set.clear();  
  171.             set.addAll(selectPosSet);  
  172.         }  
  173.     });  
  174. }  
  175.   
  176. /** 
  177.  * 添加标签 
  178.  * @param editText 
  179.  * @return 
  180.  */  
  181. private boolean addLabel(EditText editText) {  
  182.     String editTextContent = editText.getText().toString();  
  183.     //判断输入是否为空  
  184.     if (editTextContent.equals(""))  
  185.         return true;  
  186.     //判断是否重复  
  187.     for (TextView tag : labels) {  
  188.         String tempStr = tag.getText().toString();  
  189.         if (tempStr.equals(editTextContent)) {  
  190.             editText.setText("");  
  191.             editText.requestFocus();  
  192.             return true;  
  193.         }  
  194.     }  
  195.     //添加标签  
  196.     final TextView temp = getTag(editText.getText().toString());  
  197.     labels.add(temp);  
  198.     labelStates.add(false);  
  199.     //添加点击事件,点击变成选中状态,选中状态下被点击则删除  
  200.     temp.setOnClickListener(new View.OnClickListener() {  
  201.         @Override  
  202.         public void onClick(View v) {  
  203.             int curIndex = labels.indexOf(temp);  
  204.             if (!labelStates.get(curIndex)) {  
  205.                 //显示 ×号删除  
  206.                 temp.setText(temp.getText() + " ×");  
  207.                 temp.setBackgroundResource(R.drawable.label_del);  
  208.                 temp.setTextColor(Color.parseColor("#ffffff"));  
  209.                 //修改选中状态  
  210.                 labelStates.set(curIndex, true);  
  211.             } else {  
  212.                 delByTest(temp.getText().toString());  
  213.                 flowLayout.removeView(temp);  
  214.                 labels.remove(curIndex);  
  215.                 labelStates.remove(curIndex);  
  216.                 for (int i = 0; i < label_list.size(); i++) {  
  217.                     for (int j = 0; j < labels.size(); j++) {  
  218.                         if (label_list.get(i).equals(  
  219.                                 labels.get(j).getText())) {  
  220.                             tagAdapter.setSelectedList(i);  
  221.                         }  
  222.                     }  
  223.                 }  
  224.                 tagAdapter.notifyDataChanged();  
  225.             }  
  226.         }  
  227.     });  
  228.     flowLayout.addView(temp);  
  229.     //让输入框在最后一个位置上  
  230.     editText.bringToFront();  
  231.     //清空编辑框  
  232.     editText.setText("");  
  233.     editText.requestFocus();  
  234.     return true;  
  235.   
  236. }  
  237.   
  238.   
  239. /** 
  240.  * 根据字符删除标签 
  241.  * @param text 
  242.  */  
  243. private void delByTest(String text) {  
  244.   
  245.     for (int i = 0; i < all_label_List.size(); i++) {  
  246.         String a = all_label_List.get(i) + " ×";  
  247.         if (a.equals(text)) {  
  248.             set.remove(i);  
  249.         }  
  250.     }  
  251.     tagAdapter.setSelectedList(set);//重置选中的标签  
  252.   
  253. }  
  254.   
  255.   
  256. /** 
  257.  * 标签恢复到正常状态 
  258.  */  
  259. private void tagNormal() {  
  260.     //输入文字时取消已经选中的标签  
  261.     for (int i = 0; i < labelStates.size(); i++) {  
  262.         if (labelStates.get(i)) {  
  263.             TextView tmp = labels.get(i);  
  264.             tmp.setText(tmp.getText().toString().replace(" ×"""));  
  265.             labelStates.set(i, false);  
  266.             tmp.setBackgroundResource(R.drawable.label_normal);  
  267.             tmp.setTextColor(Color.parseColor("#00FF00"));  
  268.         }  
  269.     }  
  270. }  
  271.   
  272.   
  273. /** 
  274.  * 创建一个正常状态的标签 
  275.  * @param label 
  276.  * @return 
  277.  */  
  278. private TextView getTag(String label) {  
  279.     TextView textView = new TextView(getApplicationContext());  
  280.     textView.setTextSize(12);  
  281.     textView.setBackgroundResource(R.drawable.label_normal);  
  282.     textView.setTextColor(Color.parseColor("#00FF00"));  
  283.     textView.setText(label);  
  284.     textView.setLayoutParams(params);  
  285.     return textView;  
  286. }  
  287.   }  

 

注释的很详细了。其实正常一步步来就按照逻辑来就可以实现,别慌,别乱,别急躁。什么功能都能实现的。

六、源码

http://download.csdn.net/detail/u011310942/9681263

感谢 小_源 支持 磐实编程网 原文地址:
blog.csdn.net/xiaoyuan511/article/details/53144626

文章信息

发布时间:2016-11-14

作者:小_源

发布者:aquwcw

浏览次数: