關于到頂部刷新的實現,可以查看我另外一篇文章
這里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分類查看我的另外的一篇文章.