简书链接:探索drawalbeTop的弊端到顶刷新只选择tab图标旋转文字不旋转动画方案
文章字数:1496,阅读全文大约需要5分钟
关于到顶部刷新的实现,可以查看我另外一篇文章
这里tab是使用的RadioGroup,很倔强的我坚持不使用第三方,自己折腾传统老套的selector来实现。
那么想到的方案就是给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; }
}
|
缺点 旋转速度不可以调节,旋转速度非常慢
这种方法又是要手写一个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来的
这个问题是因为我是给DrawableTopRadioButton
添加的触摸事件,如果有这种需求的朋友,直接继承DrawableTopRadioButton
复写onInterceptTouchEvent
方法返回true,然后在手势里面做一些操作,包括单击的时候手动调用DrawableTopRadioButton.getRadioButton().setCheck(true)
以及调用DrawableTopRadioButton.getTopImageView().setCheck(true)
就可以解决这个更加变态的需求了,这个需求了
或者也可以给imageView和RadioButton也添加一个触摸事件类,这个类和DrawableTopRadioButton
的触摸事件类一样,这里看不懂的朋友看我另外一篇文章,叫到顶刷新实现方案
吐槽
坑已经帮大家踩完了但是,我搞这个花了很多时间的,如果要用第三方,或者手写一个 多加一点判断也是可以实现的,怪我太执着 硬是折腾RadioGroup
不过总算搞定了所有的变态需求啦!!!要研究如何修改RadioGroup
进行扩展的朋友可以点击android分类查看我的另外的一篇文章.