• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • RadioButton兼容問題修復&實現選中縮放動畫

    一個帶縮放動畫的 RadioButton

    效果如圖

    ani

    How do I use it?

    Step 1.Add it in your root build.gradle at the end of repositories:

    allprojects {
    	repositories {
    		...
    		maven { url 'https://jitpack.io' }
    	}
    }
    

    Step 2. Add the dependency

    dependencies {
             implementation 'com.github.qingyc:FixedAnimatedRadioButton:0.1'
    }
    

    一.處理低版本RadioButton問題

    RadioButton在布局中的使用

    
        <RadioGroup
            android:id="@+id/rg_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_main_bottom"
            android:gravity="bottom"
            android:orientation="horizontal"
            android:paddingTop="4dp"
            android:paddingBottom="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/main_viewpager">
    
            <com.qingyc.basekit.widget.FixedAnimatedRadioButton
                android:id="@+id/rb_capricorn"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:button="@null"
                android:checked="true"
                android:drawableTop="@drawable/main_rb_01"
                android:gravity="center"
                android:text="@string/capricorn"
                android:textColor="@color/radio_btn_text_color"
                android:textSize="12sp"/>
    
    
            <com.qingyc.basekit.widget.FixedAnimatedRadioButton
                android:id="@+id/rb_compatibility"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:button="@null"
                android:checked="false"
                android:drawableTop="@drawable/main_rb_02"
                android:gravity="center"
                android:text="@string/compatibility"
                android:textColor="@color/radio_btn_text_color"
                android:textSize="12sp"/>
    
    
            <com.qingyc.basekit.widget.FixedAnimatedRadioButton
                android:id="@+id/rb_personality"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:button="@null"
                android:checked="false"
                android:drawableTop="@drawable/main_rb_03"
                android:gravity="center"
                android:text="@string/personality"
                android:textColor="@color/radio_btn_text_color"
                android:textSize="12sp"/>
    
            <com.qingyc.basekit.widget.FixedAnimatedRadioButton
                android:id="@+id/rb_discover"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:button="@null"
                android:checked="false"
                android:drawableTop="@drawable/main_rb_04"
                android:gravity="center"
                android:text="@string/discover"
                android:textColor="@color/radio_btn_text_color"
                android:textSize="12sp"/>
    
    
        </RadioGroup>
    

    RadioButton在低版本上的問題(android 4.4)

    可以看出在低版本的模擬器中 radioButton左邊顯示了一個默認button圖標,xml中 android:button="@null" 無效

    android api 19

    而在高版本的模擬器和手機中 顯示正常

    android api 28

    RadioButton的button圖標的設置是在CompoundButton類中實現的

    android Api 28源碼

        public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
    
            final TypedArray a = context.obtainStyledAttributes(
                    attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes);
    
            final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
            if (d != null) {
                setButtonDrawable(d);
            }
    
            if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) {
                mButtonTintMode = Drawable.parseTintMode(a.getInt(
                        R.styleable.CompoundButton_buttonTintMode, -1), mButtonTintMode);
                mHasButtonTintMode = true;
            }
    
            if (a.hasValue(R.styleable.CompoundButton_buttonTint)) {
                mButtonTintList = a.getColorStateList(R.styleable.CompoundButton_buttonTint);
                mHasButtonTint = true;
            }
    
            final boolean checked = a.getBoolean(
                    com.android.internal.R.styleable.CompoundButton_checked, false);
            setChecked(checked);
            mCheckedFromResource = true;
    
            a.recycle();
    
            applyButtonTint();
        }
    
    

    a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); 獲取xml中設置的button drawable,CompoundButton內部私有成員變量 mButtonDrawable 即是

    可以看出最終會調用下面兩個方法

    
        /**
         * Sets a drawable as the compound button image given its resource
         * identifier.
         *
         * @param resId the resource identifier of the drawable
         * @attr ref android.R.styleable#CompoundButton_button
         */
        public void setButtonDrawable(@DrawableRes int resId) {
            final Drawable d;
            if (resId != 0) {
                d = getContext().getDrawable(resId);
            } else {
                d = null;
            }
            setButtonDrawable(d);
        }
    
        /**
         * Sets a drawable as the compound button image.
         *
         * @param drawable the drawable to set
         * @attr ref android.R.styleable#CompoundButton_button
         */
        public void setButtonDrawable(@Nullable Drawable drawable) {
            if (mButtonDrawable != drawable) {
                if (mButtonDrawable != null) {
                    mButtonDrawable.setCallback(null);
                    unscheduleDrawable(mButtonDrawable);
                }
    
             mButtonDrawable = drawable
    
                if (drawable != null) {
                    drawable.setCallback(this);
                    drawable.setLayoutDirection(getLayoutDirection());
                    if (drawable.isStateful()) {
                        drawable.setState(getDrawableState());
                    }
                    drawable.setVisible(getVisibility() == VISIBLE, false);
                    setMinHeight(drawable.getIntrinsicHeight());
                    applyButtonTint();
                }
            }
        }
        
    

    可以看出不管是在xml 或者代碼中設置RadioButton的button 最終都調用 setButtonDrawable(@Nullable Drawable drawable)

    對比Android api 19源碼

    點擊查看

    
        public void setButtonDrawable(Drawable d) {
            if (d != null) {
                if (mButtonDrawable != null) {
                    mButtonDrawable.setCallback(null);
                    unscheduleDrawable(mButtonDrawable);
                }
                d.setCallback(this);
                d.setVisible(getVisibility() == VISIBLE, false);
                mButtonDrawable = d;
                setMinHeight(mButtonDrawable.getIntrinsicHeight());
            }
    
            refreshDrawableState();
        }
    

    可以看出 輸入drawable為null時根本沒有調用 mButtonDrawable = drawable 把mButtonDrawable置空

    問題處理

      override fun setButtonDrawable(buttonDrawable: Drawable?) {
                 // QTIP: 2019-04-28 修復低版本(android4.4)設置按鈕為null時顯示默認按鈕
                 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
                     try {
                         val clazz = CompoundButton::class.java
                         val field = clazz.getDeclaredField("mButtonDrawable")
                         field.isAccessible = true
                         field.set(this, null)
                     } catch (e: Exception) {
                         e.printStackTrace()
                     }
                 } else {
                     super.setButtonDrawable(buttonDrawable)
                 }
      }
    

    二 實現點擊RadioButton縮放動畫

    調用時機 check狀態變化時

    
        override fun setChecked(checked: Boolean) {
            super.setChecked(checked)
            if (width == 0 || height == 0) {
                return
            }
            if (checked) {
                val animator = ValueAnimator.ofFloat(minScaleRate, maxScaleRate)
                animator.addUpdateListener(this)
                animator.duration = 300
                animator.start()
            } else {
                if (animatedScaleRate != 1f) {
                    val animator = ValueAnimator.ofFloat(animatedScaleRate, 1f)
                    animator.addUpdateListener(this)
                    animator.duration = 0
                    animator.start()
                }
            }
        }
    

    RadioButton選中動畫實現

       override fun onAnimationUpdate(animation: ValueAnimator?) {
            animatedScaleRate = animation?.animatedValue as Float
            try {
                //1.保存圖標默認位置
                if (mDefaultDrawableBounds == null) {
                    mDefaultDrawableBounds = arrayOfNulls(4)
                    compoundDrawables.forEachIndexed { index, drawable ->
                        drawable?.let {
                            val rect = Rect(drawable.bounds)
                            mDefaultDrawableBounds?.set(index, rect)
                        }
                    }
                }
                var leftDrawable: Drawable? = null
                var rightDrawable: Drawable? = null
                var topDrawable: Drawable? = null
                var bottomDrawable: Drawable? = null
                //2.獲取radioButton中設置的圖標的drawable
                compoundDrawables.forEachIndexed { index, drawable ->
                    drawable?.let {
                        mDefaultDrawableBounds?.get(index)?.let { mDefaultDrawableBounds ->
                            val copyBounds = Rect(mDefaultDrawableBounds)
                            //3.動態縮放RadioButton的圖標
                            copyBounds.let {
                                copyBounds.left = mDefaultDrawableBounds.left
                                copyBounds.right =
                                    mDefaultDrawableBounds.right - (mDefaultDrawableBounds.width() * (1 - animatedScaleRate)).toInt()
                                copyBounds.top =
                                    mDefaultDrawableBounds.top + (mDefaultDrawableBounds.height() * (1 - animatedScaleRate)).toInt() / 2
                                copyBounds.bottom =
                                    mDefaultDrawableBounds.bottom - (mDefaultDrawableBounds.height() * (1 - animatedScaleRate)).toInt() / 2
                                when (index) {
                                    0 -> {
                                        leftDrawable = drawable
                                        leftDrawable?.bounds = copyBounds
    
                                    }
                                    1 -> {
                                        topDrawable = drawable
                                        topDrawable?.bounds = copyBounds
                                    }
                                    2 -> {
                                        rightDrawable = drawable
                                        rightDrawable?.bounds = copyBounds
                                    }
                                    3 -> {
                                        bottomDrawable = drawable
                                        bottomDrawable?.bounds = copyBounds
                                    }
                                }
                            }
                        }
                    }
                }
                //4.更新圖標大小和位置
                setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable)
    
            } catch (e: Exception) {
            }
        }
    

    github源碼

    版權聲明:本文為qingyc原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qingyc/article/details/89716267

    智能推薦

    爬蟲項目實戰八:爬取天氣情況

    爬取天氣情況 目標 項目準備 接口分析 代碼實現 效果顯示 寫入本地 目標 根據天氣接口,爬取接下來一周的天氣情況。 項目準備 軟件:Pycharm 第三方庫:requests,BeautifulSoup,csv 接口地址:http://api.k780.com:88/?app=weather.future&weaid=城市名&appkey=10003&sign=b59bc...

    關于web項目的目錄問題

    先給段代碼: 上面這個代碼一直出錯,我不知道原因,后面不停的查找資料發現了問題:我的web項目輸出目錄有問題,因為我也是第一次用idea寫web項目,發現很多bug 其實都沒有太大問題,我們需要注意的是你必須在out這個輸出文件夾中擁有這個文件,out輸出文件夾會默認過濾這些文件...

    二叉搜索樹轉化為雙向鏈表

    題目描述: 輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的循環雙向鏈表。要求不能創建任何新的節點,只能調整樹中節點指針的指向。 為了讓您更好地理解問題,以下面的二叉搜索樹為例: 我們希望將這個二叉搜索樹轉化為雙向循環鏈表。鏈表中的每個節點都有一個前驅和后繼指針。對于雙向循環鏈表,第一個節點的前驅是最后一個節點,最后一個節點的后繼是第一個節點。 下圖展示了上面的二叉搜索樹轉化成的鏈表。&ldqu...

    Cocos2d-x 2.0 網格動畫深入分析

    [Cocos2d-x相關教程來源于紅孩兒的游戲編程之路CSDN博客地址:http://blog.csdn.net/honghaier] 紅孩兒Cocos2d-X學習園地QQ2群:44208467加群寫:Cocos2d-x 紅孩兒Cocos2d-X學習園地QQ群:249941957[暫滿]加群寫:Cocos2d-x 本章為我的Cocos2d-x教程一書初稿。望各位看官多提建議! Cocos2d-x ...

    vue 子組件傳值父組件 emit

    vue 子組件傳值父組件  emit    ...

    猜你喜歡

    解決Python數據可視化中文部分顯示方塊問題

    一、問題 代碼如下,發現標題的中文顯示的是方塊 如下圖 二、解決方法 一般數據可視化使用matplotlib庫,設置中文字體可以在導入之后添加兩句話(這里的SimHei指的是黑體,KaiTi指的是楷體) 三、效果 1.黑體: 2.楷體: 具體的其他字體可以在matplotlib\mpl-data\fonts\ttf找到~ 四、Windows的常用字體 黑體、楷體、仿宋是可以用的,其他的字體可能需要...

    Linux的LVM掛載(Centos)

    LVM掛載 1、虛擬機添加新增磁盤(如已添加可略過) 2、查看是否有新的硬盤 3、對磁盤分區 4、LVM磁盤創建 參考地址: https://blog.51cto.com/11555417/2158443 1、虛擬機添加新增磁盤(如已添加可略過) 1.點擊虛擬機,選擇硬盤,點擊添加,選擇SCSI硬盤,添加硬盤(如下圖所示)。 2、查看是否有新的硬盤 可以看到 /dev/sdb 是我們新建的磁盤5G...

    Java四大元注解介紹

    Java四大元注解介紹 什么是元注解? 元注解就是注解到注解上的注解。它們被用來提供對其它 annotation類型作說明。 Java5.0定義的元注解: @Retention、@Documented、@Target、@Inherited,這些類型和它們所支持的類在java.lang.annotation包中可以找到。如圖所示: 接下來我們看一下每個元注解的作用和相應分參數的使用說明。 @Docu...

    Webpack實戰(六):如何優雅地運用樣式CSS預處理

    上一篇文章中,我主要分享了《Webpack如何分離樣式文件》CSS 預處理器是一個能讓你通過預處理器自己獨有的語法來生成CSS的程序,css預處理指的是在開發中我們經常會使用一些樣式預編譯語言,在項目打包過程中再將這些預編譯語言轉換成css。這些預編譯語言具有便捷的特性,使用這些,可以減少代碼編寫,降低項目的開發和維護成本,提高開發效率。 目前比較流行的幾種主要是Sass、LESS、Stylus、...

    [AHOI2008]緊急集合 / 聚會

    傳送門 這題題面有毒,其實就是讓你求將樹上三個點都移到任意一點,三個點最少一共經過多少條邊。 在某種意義上可以理解為三個點的LCA? 顯然我們會將這三個點移到其中兩個點的LCA上去。那么具體選擇哪個LCA呢? 我們發現,要么三個點的LCA都相同,這個時候只有一種選擇;絕對不可能出現三個點的LCA都不同的情況。很容易證明,這里略去。 那么如果有兩個點的LCA相同呢?我們會選擇那個“與眾不...

    精品国产乱码久久久久久蜜桃不卡