java - 如何获得中性按钮的标准颜色

标签 java android android-layout android-resources android-theme

我正在使用 style="?android:attr/buttonBarNeutralButtonStyle"的按钮

<Button
    style="?android:attr/buttonBarNeutralButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="Sign in" />

我想获取它的颜色,这样我也可以将它与其他 View 元素一起使用。

目前我正在读取它的颜色值,如下所示:

int color;

View button = findViewById(R.id.passwordSigninButton);
if ((button != null) && (button instanceof Button))
  color = ((Button) button).getCurrentTextColor();
// -16738680

...而且效果很好。但我更愿意直接获取与适用样式关联的颜色,而不需要使用实际的按钮,以防我想在布局中没有按钮的情况下使用它。

所以我尝试了这种方法:

TypedValue typedValue = new TypedValue();

getApplicationContext().getTheme().resolveAttribute(
    android.R.attr.buttonBarNeutralButtonStyle, typedValue, true);

TypedArray typedArray = context.obtainStyledAttributes(
    typedValue.data, new int[]{android.R.attr.textColor});

int color = typedArray.getColor(0, -1);
// -1

typedArray.recycle();

但是我得到了-1,这意味着我没有得到我期望的颜色。

如何从 android.R.attr.buttonBarNeutralButtonStyle 样式获取颜色?

最佳答案

请参阅下面的直接推导更新。

确定中性按钮文本颜色的方法是尝试复制 Android 确定颜色所采取的步骤。正如我认为我们从这个问题的回答中看到的那样,这种处理是在幕后进行的,并且可能会随着版本的不同而变化。我确信 Android 开发人员会随意更改底层实现,只要结果相同,因此,即使您可以获得今天有效的解决方案,它也会很脆弱,明天可能会崩溃。

您确实有一个解决方案,但它涉及创建您想要避免的布局。我建议使用以下方法,我相信该方法将满足您的目的,并且更加健壮,并且不需要布局文件。您表明您正在使用 android.support.v7.app.AppCompatDialog 创建 AppCompatButton 按钮。

以下两行将为您提供中性按钮文本的颜色,无需布局或提取属性的复杂性。我已经在运行 API 22 的模拟器和运行 API 24 的三星 S7 上对此进行了测试,两个结果都与显式布局所看到的结果一致。

android.support.v7.widget.AppCompatButton button =
    new android.support.v7.widget.AppCompatButton(this, null,
    android.R.attr.buttonBarNeutralButtonStyle);
int color = button.getCurrentTextColor();
<小时/>

直接推导

虽然我相信上面的解决方案是最好的,但下面的代码将为所有 API 派生中性按钮的默认颜色。此方法只是查找 textColor 属性,如果未定义,则查找 textAppearance 并查看其中定义的 textColor。看起来不同 API 之间的区别在于如何指定颜色。该解决方案可能足够强大,可以承受后续更新,但买者自负

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        android.support.v7.widget.AppCompatButton button =
            new android.support.v7.widget.AppCompatButton(this, null, android.R.attr.buttonBarNeutralButtonStyle);
        Log.d("MainActivity", String.format("<<<< Button color = 0x%08X", button.getCurrentTextColor()));
        Log.d("MainActivity", String.format("<<<< Derived color = 0x%08X", getNeutralButtonColor(Color.WHITE)));
    }

    private int getNeutralButtonColor(int defaultColor) {
        TypedArray ta;
        int color = defaultColor;
        boolean colorFound = false;
        int textColorResId;
        final int baseAttr = R.attr.buttonBarNeutralButtonStyle;

        // Look for an explicit textColor attribute and use it if it is defined.
        ta = getTheme().obtainStyledAttributes(null, new int[]{android.R.attr.textColor}, baseAttr, 0);
        textColorResId = ta.getResourceId(0, -1);
        if (textColorResId == -1) { // try to get color if not resource id
            int type = ta.getType(0);
            if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
                color = ta.getColor(0, defaultColor);
                colorFound = true;
            }
        }
        ta.recycle();

        if (textColorResId == -1 && !colorFound) {
            // No color, yet. See if textAppearance is defined.
            ta = obtainStyledAttributes(null, new int[]{android.R.attr.textAppearance},
                                        baseAttr, 0);
            int textAppearanceId = ta.getResourceId(0, -1);
            if (textAppearanceId != -1) {
                // OK, textAppearance is defined. Get the embedded textColor.
                ta.recycle();
                ta = obtainStyledAttributes(textAppearanceId, new int[]{android.R.attr.textColor});
                textColorResId = ta.getResourceId(0, -1);
                if (textColorResId == -1) { // try to get color if not resource id
                    int type = ta.getType(0);
                    if (type >= TypedValue.TYPE_FIRST_COLOR_INT && type <= TypedValue.TYPE_LAST_COLOR_INT) {
                        color = ta.getColor(0, defaultColor);
                        colorFound = true;
                    }
                }
            }
            ta.recycle();
        }

        if (textColorResId != -1 && !colorFound) {
            ColorStateList colorStateList = AppCompatResources.getColorStateList(this, textColorResId);
            if (colorStateList != null) {
                color = colorStateList.getDefaultColor();
                colorFound = true; // in case needed later
            }
        }

        return color;
    }

    @SuppressWarnings("unused")
    private static final String TAG = "MainActivity";
}

关于java - 如何获得中性按钮的标准颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49365139/

相关文章:

执行过程时 JavaFX 不确定进度条

java - FlyingSaucer ITextRenderer 完成错误(不平衡的保存/恢复和空白 PDF)

java - Android ListFragment 打乱了最初未呈现的元素的顺序

android - 适用于所有安卓设备的响应式设计

android - 在 Android 中为动态创建的按钮实现 OnClickListener

android - 无法在布局中对齐 TextView 和 Checkbox

android - Material Design 两行列表

java - DBUnit 有没有办法自动创建表?

java - 将字符串[]转换为整数[]

Android 应用程序 - 逻辑/原则