RadioButton兼容問題修復&實現選中縮放動畫
一個帶縮放動畫的 RadioButton
效果如圖
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" 無效
而在高版本的模擬器和手機中 顯示正常
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) {
}
}
智能推薦
爬蟲項目實戰八:爬取天氣情況
爬取天氣情況 目標 項目準備 接口分析 代碼實現 效果顯示 寫入本地 目標 根據天氣接口,爬取接下來一周的天氣情況。 項目準備 軟件: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 ...
猜你喜歡
解決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相同呢?我們會選擇那個“與眾不...