探索drawalbeTop的弊端到頂刷新只選擇tab圖標旋轉文字不旋轉動畫方案

關于到頂部刷新的實現,可以查看我另外一篇文章

這里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:textandroid: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分類查看我的另外的一篇文章.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 【Android 動畫】 動畫分類補間動畫(Tween動畫)幀動畫(Frame 動畫)屬性動畫(Property ...
    Rtia閱讀 6,231評論 1 38
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,245評論 4 61
  • 如果我曾經堅持做一件有意義的事一年,兩年,三年,我應該是一個比現在“偉大”的多的一個人吧??上У木褪菦]有如果。從現...
    光照君閱讀 158評論 0 0
  • 目錄上一篇:【第十九章:我陪你走(第一卷:大提琴之殤)】 【第二十章:誰對誰錯·第一卷:大提琴之殤】 偞兒搖搖頭:...
    錢多歡閱讀 387評論 -1 0
  • 話說,要一萬小時才能完全掌握一門技能,成為這個領域的專家。但這一萬小時從哪里來呢?不是睡來的,也不是等來的,而應該...
    Mr航閱讀 2,853評論 0 0