关于到顶部刷新的实现,可以查看我另外一篇文章
这里tab是使用的RadioGroup,很倔强的我坚持不使用第三方,自己折腾传统老套的selector来实现。
方案1 只修改DrawableRadioButton 和添加xml动画
那么想到的方案就是给drawableTop设置动画xml 布局。
结果发现不旋转,在网上找到了一个方案 继承它就可以实现旋转:
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
有这么一段代码
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分类查看我的另外的一篇文章.