调用需要 API 级别 29(当前最低为 21):`android.widget.NumberPicker#setTextColor`

2024-04-01

我想使用 setTextColor 更改选定的文本颜色字段。但是 Android Studio 给了我这个错误。我应该怎么办?最小 SDK 为 21。 这是我的 CustomNumberPicker 类的代码:

import android.annotation.TargetApi
import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.NumberPicker
import android.widget.NumberPicker.OnScrollListener
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.widget.TextViewCompat
import ir.partsoftware.cup.R
import timber.log.Timber

class CustomNumberPicker : NumberPicker {

    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        init()
    }

    private fun init() {
        setDividerColor(ContextCompat.getColor(context, R.color.color_secondary))
        setNumberPickerTextColor(this, ContextCompat.getColor(context, R.color.color_secondary))
        this.setOnValueChangedListener { picker, oldVal, newVal ->
            setNumberPickerTextColor(this, ContextCompat.getColor(context, R.color.color_secondary))
        }
        this.setOnScrollListener { numberPicker, scrollState ->
            setNumberPickerTextColor(this, ContextCompat.getColor(context, R.color.color_secondary))
        }
    }

    private fun setNumberPickerTextColor(numberPicker: NumberPicker, color: Int) {
        if (VERSION.SDK_INT >= VERSION_CODES.Q) {
            numberPicker.textColor = color
        } else {
            val count = numberPicker.childCount
            for (i in 0 until count) {
                val child = numberPicker.getChildAt(i)
                if (child is EditText) {
                    try {
                        child.setTextColor(color)
                        val fieldSelectorWheelPaint = numberPicker.javaClass.getDeclaredField("mSelectorWheelPaint")
                        val paint = fieldSelectorWheelPaint[numberPicker] as Paint
                        paint.color = color
                        fieldSelectorWheelPaint.isAccessible = true
                        numberPicker.invalidate()
                    } catch (ex: java.lang.Exception) {
                        // Ignore
                    }
                }
            }
        }
    }

    private fun setDividerColor(@ColorInt color: Int) {
        try {
            val fDividerDrawable =
                NumberPicker::class.java.getDeclaredField("mSelectionDivider")
            fDividerDrawable.isAccessible = true
            val d = fDividerDrawable[this] as Drawable
            DrawableCompat.setTint(d, color)
            d.invalidateSelf()
            postInvalidate()
        } catch (e: Exception) {
            Timber.d(e)
        }
    }

    override fun addView(
        child: View,
        index: Int,
        params: ViewGroup.LayoutParams
    ) {
        super.addView(child, index, params)
        updateView(child)
    }

    private fun updateView(view: View) {
        if (view is EditText) {
            try {
                TextViewCompat.setTextAppearance(view, R.style.TextAppearance_PartPay_NumPicker)
                val customFont: Typeface? = ResourcesCompat.getFont(context, R.font.iran_yekan)
                view.typeface = customFont
                //  setNumberPickerTextColor(ContextCompat.getColor(context, R.color.color_secondary))
            } catch (e: Exception) {
                Timber.d(e)
            }
        }
    }
}

尝试下一个代码。当 API 不可访问时将使用反射:

public void setNumberPickerTextColor(final NumberPicker numberPicker, final int color){

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        numberPicker.setTextColor(color);
    }
    else {
        final int count = numberPicker.getChildCount();

        for (int i = 0; i < count; i++) {

            final View child = numberPicker.getChildAt(i);

            if (child instanceof EditText) {
                try {
                    ((EditText)child).setTextColor(color);
                    numberPicker.invalidate();

                    final Field fieldSelectorWheelPaint = numberPicker.getClass().getDeclaredField("mSelectorWheelPaint");
                    boolean     isAccessible            = fieldSelectorWheelPaint.isAccessible();
                    fieldSelectorWheelPaint.setAccessible(true);
                    final Paint paint = (Paint)fieldSelectorWheelPaint.get(numberPicker);

                    if (paint != null){
                        paint.setColor(color);
                        fieldSelectorWheelPaint.setAccessible(isAccessible);
                        numberPicker.invalidate();
                    }

                    final Field fieldSelectionDivider = numberPicker.getClass().getDeclaredField("mSelectionDivider");
                    isAccessible = fieldSelectionDivider.isAccessible();
                    fieldSelectionDivider.setAccessible(true);
                    fieldSelectionDivider.set(numberPicker, null);
                    fieldSelectionDivider.setAccessible(isAccessible);
                    numberPicker.invalidate();
                }
                catch (Exception ex) {
                    // Ignore
                }
            }
        }
    }
}

您可以在第一次获得对该控件的引用时调用此方法,此外,如果滚动后颜色没有持续存在,则挂钩侦听器,例如 next:

numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
    @Override
    public void onValueChange(final NumberPicker picker, final int oldVal, final int newVal) {
        setNumberPickerTextColor(numberPicker, Color.RED);
    }
});

或者,您也可以挂钩滚动侦听器,尽管上面的 setOnValueChangedListener 示例更加优化,因为它只会在值更改时执行更新。要改进下一个滚动方法,您可以检查scrollState是否处于空闲状态,因此仅在滚动结束时调用它:

numberPicker.setOnScrollListener(new NumberPicker.OnScrollListener() {
    @Override
    public void onScrollStateChange(final NumberPicker numberPicker, final int scrollState) {
        setNumberPickerTextColor(numberPicker, Color.RED);
    }
});

UPDATE: 下一部分仅针对您更新的问题代码。

问题是您正在扩展 NumberPicker 类,在这种情况下您需要使用获取声明字段 on the 超一流。我的上述答案只能在不扩展 NumberPicker 类时使用。 此外,您还放置了是可访问的在错误的行中,需要稍微靠前才能访问。

接下来是对代码的更正,可以在扩展 NumberPicker 类时完美使用。你可以看到获取声明字段前面是超类, and 是可访问的位于正确的位置:

private fun setNumberPickerTextColor(numberPicker: NumberPicker, color: Int) {
    if (VERSION.SDK_INT >= VERSION_CODES.Q) {
        numberPicker.textColor = color
    } else {
        val count = numberPicker.childCount
        for (i in 0 until count) {
            val child = numberPicker.getChildAt(i)
            if (child is EditText) {
                try {
                    child.setTextColor(color)
                    val fieldSelectorWheelPaint = numberPicker.javaClass.superclass.getDeclaredField("mSelectorWheelPaint")
                    fieldSelectorWheelPaint.isAccessible = true
                    val paint = fieldSelectorWheelPaint[numberPicker] as Paint
                    paint.color = color
                    numberPicker.invalidate()
                } catch (ex: java.lang.Exception) {
                    // Ignore
                }
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

调用需要 API 级别 29(当前最低为 21):`android.widget.NumberPicker#setTextColor` 的相关文章

随机推荐