正式开发android也有一个月左右了,公司的一个小的app基本完成,没什么事干,想起了搞点事。看到别人写的自定义控件用着挺爽的,也想着自己写一个,无奈能力有限,写了第一个属于自己的自定义控件费尽了心事。废话不多说,先上来效果图。(背景控件原型知乎app,而又不同于其效果)
(知乎原型图)
(我的效果图)
下面我说下我的思路:
制作标签横向列表,通过动态添加到父布局中,父布局采用的是:HorizontalScrollView,然后通过AddView(View v) 方法添加子控件textView 。但是手机的屏幕宽度是有限的,就会出现下图中未处理溢出的情形。因此我们需要做一下处理,处理办法很简单。
通过重写HorizontalScrollView的
onLayout
(
boolean
paramBoolean
, int
paramInt1
, int
paramInt2
, int
paramInt3
, int
paramInt4)方法来处理;onLayout 方法是来布局子控件,正好我们需要处理子控件,用这个方法再好不过了;对子控件的处里的代码也不多,下面是我的处理方法,如果有做的不妥的话,请指正。
- 动态添加TextView
public void setTopic(List<Topic> list) { removeAllViews(); this.b = false; this.topics = list; LinearLayoutCompat linearLayoutCompat = new LinearLayoutCompat(getContext()); linearLayoutCompat.setOrientation(LinearLayoutCompat.HORIZONTAL); Iterator iterator = topics.iterator(); while (iterator.hasNext()) { final Topic localTopic = (Topic) iterator.next(); TextView localTextView = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.text, linearLayoutCompat, false); localTextView.setText(localTopic.getName()); localTextView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getContext(), localTopic.getName(), Toast.LENGTH_SHORT).show(); } }); linearLayoutCompat.addView(localTextView); } addView(linearLayoutCompat); }
- 处理溢出的TextView
需要注意的还要做一下细节处理,HorizontalScrollView 能左右滑动,我们要关闭这个功能。下面是处理方法:@Override protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4); Log.e(TAG, "onLayout------------------------------" + paramBoolean); if (paramBoolean) { final LinearLayoutCompat linearLayout = (LinearLayoutCompat) getChildAt(0); // getChildAt(postion) ViewGroup 里面的方法 用来获取指定位置的视图,由于下边的setTopic(List<Topic> list)方法中添加的控件是 // 一个LinearLayoutCompat布局,所以这里获取的就是他了 int count = linearLayout.getChildCount();//计算一个LinearLayoutCompat布局中子控件的个数 TextView localTextView = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.text, linearLayout, false); localTextView.setText("...");//定义一个文本内容为"..."的TextView,作为溢出内容填充 int width = 0;//初始化linearLayout宽度 for (int i = 0; i < count; i++) {//遍历所用TextView控件,并累加计算当前linearLayout宽度 width += linearLayout.getChildAt(i).getWidth(); if (width+localTextView.getWidth() > getWidth()) {//如果当前遍历的第i个TextView时候,linearLayout宽度大于父布局宽度 linearLayout.removeViews(i - 1, count - i + 1); // 将当前TextView以后的所有TextView移除 linearLayout.addView(localTextView);//添加文本内容为"..."的TextView到末尾 break; } } } }
就这么简单就实现,突然发现也没多难吗,耐心了解android的控件内部实现还是很重要的。@Override public boolean onTouchEvent(MotionEvent ev) { return false; }
源码下载 (项目创建使用AndroidSutdio创建)