简书链接:探索drawalbeTop的弊端到顶刷新只选择tab图标旋转文字不旋转动画方案
文章字数:1496,阅读全文大约需要5分钟
关于到顶部刷新的实现,可以查看我另外一篇文章

这里tab是使用的RadioGroup,很倔强的我坚持不使用第三方,自己折腾传统老套的selector来实现。

方案1 只修改DrawableRadioButton 和添加xml动画

那么想到的方案就是给drawableTop设置动画xml 布局。
结果发现不旋转,在网上找到了一个方案 继承它就可以实现旋转:

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
public class DrawableRadioButton extends android.support.v7.widget.AppCompatRadioButton {

public DrawableRadioButton(Context context) {
super(context);
}

public DrawableRadioButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

public DrawableRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
}

int textWidth;
int textHeight;
Drawable mDrawableLeft = null;
int startDrawableX = 0;
int startDrawableY = 0;

@Override
protected void onFinishInflate() {
super.onFinishInflate();
initText();
}

private void initText() {
String textStr = super.getText().toString();
Rect rect = new Rect();
getPaint().getTextBounds(textStr, 0, textStr.length(), rect);
getPaint().setColor(getTextColors().getDefaultColor());
getPaint().setTextSize(getTextSize());
textWidth = rect.width();
textHeight = rect.height();

}

@Override
protected void onDraw(Canvas canvas) {
if (mDrawableLeft == null) mDrawableLeft = getCompoundDrawables()[0];

if (mDrawableLeft == null) {
super.onDraw(canvas);
return;
}
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = this.mDrawableLeft.getIntrinsicWidth();
int drawableHeight = this.mDrawableLeft.getIntrinsicHeight();
startDrawableX = (getWidth() >> 1) - ((drawablePadding + textWidth + drawableWidth) >> 1);
startDrawableY = (getHeight() >> 1) - (drawableHeight >> 1);
//画旋转图片
canvas.save();
canvas.translate(startDrawableX, startDrawableY);
this.mDrawableLeft.draw(canvas);
canvas.restore();

//画文字
int boxht = this.getMeasuredHeight() - this.getExtendedPaddingTop() - this.getExtendedPaddingBottom();
int textht = getLayout().getHeight();
int voffsetText = boxht - textht >> 1;
canvas.save();
canvas.translate((float) (startDrawableX + drawableWidth + drawablePadding), (float) (getExtendedPaddingTop() + voffsetText));
getLayout().draw(canvas);
canvas.restore();
}

@Override
public void invalidateDrawable(Drawable drawable) {
// super.invalidateDrawable(drawable);
final Rect dirty = drawable.getBounds();
int scrollX = 0;
int scrollY = 0;
if (drawable == this.mDrawableLeft) {
scrollX = startDrawableX;
scrollY = startDrawableY;
}
this.invalidate(dirty.left + scrollX - 2, dirty.top + scrollY - 2, dirty.right + scrollX + 2, dirty.bottom + scrollY + 2);
}

public Drawable getDrawableLeft() {
return mDrawableLeft;
}

}

缺点 旋转速度不可以调节,旋转速度非常慢

方案2 使用我我之前写的RadioGroupX少量的改动实现 且还兼容原来的RadioButton

这种方法又是要手写一个RadioButton了,我在这里称之

DrawableTopRadioButton
如何实现的如果喜欢看源码的直接点击源码,下面我来说说我踩到的坑

大致原理就是添加一个相对布局然后从上大小放入图片控件和RadioButton控件 然后小红点依然支持,所以我是从小红点view拷贝过来的.我自己写的代码我也不想重写啊,这么多属性,多累啊

踩坑1 添加上去是空白,文字和图片都不显示.

我在做这个的时候浪费了太多时间了,因为我拷贝我另外一份自己写的,实际上是自定义的drawableTop和自定义的text属性,我傻乎乎的一直用android:text android:drawableTop 结果一直空白,郁闷死了, 用分析层级工具查看也竟然出现各种奇葩的问题,也并没有说添加进去了,而且竟然提示还是之前写的LinearLayout 我明明改成RelativeLayout了的然后各种编译,漫长的时间,最后受不到了,我直接跑模块运行提升速度, 总之太复杂太粗心了,结果浪费了1上午时间才恍然大悟,我还以为是编译器出毛病了,明明添加进去了竟然用分析工具看不到child节点,包括断点调试也没发现问题..结果是直接把第三个支持小红点的配置弄进去发现预览都出效果了,果然就好了.

踩坑2 不能使用传统的findById找 index了

选中内部的radiobutton 然后用group.indexOf() findById()一直找不到child.导致idnex=-1解决方法给内部的radiobutton设置的id,和这个DrawableTopRadioButton的id一样,为何只能这样原因也是为了兼容某个接口不得不这么做,这个接口必须实现 void onCheckedChanged(CompoundButton buttonView, boolean isChecked);我内部回传的时候传递的是只能传递内部的RadioButton 因为它才是继承CompoundButton 的,如果不这样传递,那么又要修改大量源码.而且很难兼容系统的RadioButton
在系统的RadioGroup有这么一段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// prevents from infinite recursion
if (mProtectFromCheckedChange) {
return;
}

mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;

int id = buttonView.getId();
setCheckedId(id);
}
}

这里在初始化的时候就添加了一个监听,所以我不能大改动,但是又要再触发的时候传递一个CompoundButton 又要让findById 也能找到对应的索引,我就只能把内部的RadioButton当做替身传递进去.

踩坑3 imageview不能使用select选择器导致点图片无法选中tab改变颜色

经过万能的搜索找到了相关的代码 也就是说要实现Checkable才能实现选择器的.所以给它正好之后,改成单选,就完事
具体怎么实现看源码

踩坑4 点击图片并不能进行排斥,虽然选中了,但是没回调。

解决方案
给图片设置一个点击事件,然后点击之后手动调用radiobutton的setCheck方法. 因为这里绑定的是radioButton能进行排斥的只有它,而且排斥也是根据id来的

踩坑5 不能点击图片或者点击、双击 radiobutton进行点击刷新 到顶部

这个问题是因为我是给DrawableTopRadioButton添加的触摸事件,如果有这种需求的朋友,直接继承DrawableTopRadioButton复写onInterceptTouchEvent方法返回true,然后在手势里面做一些操作,包括单击的时候手动调用DrawableTopRadioButton.getRadioButton().setCheck(true)以及调用DrawableTopRadioButton.getTopImageView().setCheck(true)就可以解决这个更加变态的需求了,这个需求了
或者也可以给imageView和RadioButton也添加一个触摸事件类,这个类和DrawableTopRadioButton的触摸事件类一样,这里看不懂的朋友看我另外一篇文章,叫到顶刷新实现方案

吐槽

坑已经帮大家踩完了但是,我搞这个花了很多时间的,如果要用第三方,或者手写一个 多加一点判断也是可以实现的,怪我太执着 硬是折腾RadioGroup 不过总算搞定了所有的变态需求啦!!!要研究如何修改RadioGroup进行扩展的朋友可以点击android分类查看我的另外的一篇文章.