有没有一种通用的方法可以找到适用于视图的样式?

Posted

技术标签:

【中文标题】有没有一种通用的方法可以找到适用于视图的样式?【英文标题】:Is there a general way to find the styles that apply to a View? 【发布时间】:2015-11-29 03:57:42 【问题描述】:

一般来说,您如何找到要覆盖的主题属性以改变任何 UI 元素的外观?

目前我依赖于浏览框架源文件:values.xml 中的主题定义(通常是支持库变体)、attrs.xml 中的属性定义和 R.styleable 类文档。

但这完全是偶然的。这不仅非常耗时,而且有时我会完全错过,例如,我一直试图找出如何更改 DatePickerDialog 的“确定”和“取消”按钮中的文本样式,但没有成功。随意使用它作为一个例子,但如果你这样做,请概述你的发现过程。我正在寻找的答案是如何发现任何 UI 元素的应用样式,

还是没有确定的方法可以找出答案?你只需要知道吗?

【问题讨论】:

我在这里回答了这个确切的问题:How to explore styling in android。将此信息与以下答案一起使用应该可以解决您的问题:Change Datepicker dialog color for Android 5.0. @Vikram,这非常有帮助,谢谢。不过,Quelle horreur ;) 是的,How to explore styling in android,虽然很贴切,但我想对搜索引擎不太友好。很高兴您发现它很有用。 【参考方案1】:

寻找如何在 Android 上更改小部件的样式一直很麻烦。例如,DatePickerDialog 具有不同的 Holo 和 Material 设计风格。因此,对话框的样式可能取决于 SDK 值或您是否使用 AppCompat 库。文档也很少。

如果像Hierarchy Viewer 这样的工具能够显示小部件的属性和当前主题,那就太好了。但是,我还没有遇到过这样的工具。

我们可以在视图创建后获取当前的主题和属性。以下是我在DatePickerDialog 上编写和测试的几种方法来查找正在使用的样式:


从上下文中获取当前主题:

static String getThemeNameFromContext(Context context) 
    Resources.Theme theme = context.getTheme();
    String themeName;
    try 
        Field field = theme.getClass().getDeclaredField("mThemeResId");
        if (!field.isAccessible()) 
            field.setAccessible(true);
        
        int themeResId = field.getInt(theme);
        themeName = context.getResources().getResourceEntryName(themeResId);
     catch (Exception e) 
        // If we are here then the context is most likely the application context.
        // The theme for an application context is always "Theme.DeviceDefault"
        themeName = "Theme.DeviceDefault";
    
    return themeName;

获取属性的名称/值:

static String getResourceName(Context context, int attribute) 
    TypedArray typedArray = context.obtainStyledAttributes(new int[]attribute);
    try 
        int resourceId = typedArray.getResourceId(0, 0);
        return context.getResources().getResourceEntryName(resourceId);
     finally 
        typedArray.recycle();
    


在下面的示例中,我创建了一个DatePickerDialog,并使用上述方法获得了对话框使用的主题和属性值以及对话框的正按钮:

// Create the DatePickerDialog
DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(),
        new DatePickerDialog.OnDateSetListener() 

            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) 

            
        , 2015, Calendar.SEPTEMBER, 9);
// Show the dialog
datePickerDialog.show();

// Get the positive button from the dialog:
Button positiveButton = datePickerDialog.getButton(DatePickerDialog.BUTTON_POSITIVE);
// Get the theme used by this dialog
String theme = getThemeNameFromContext(datePickerDialog.getContext());
// Get the date picker style used by the dialog
String datePickerStyle = getResourceName(datePickerDialog.getContext(), android.R.attr.datePickerStyle);
// Get the style of the positive button:
String buttonStyle = getResourceName(positiveButton.getContext(), android.R.attr.buttonStyle);

Log.i("LOGTAG", "Theme: " + theme);
Log.i("LOGTAG", "datePickerStyle: " + positiveButton);
Log.i("LOGTAG", "buttonStyle: " + buttonStyle);

在我的测试项目中,我得到了 theme、datePickerStyle 和 buttonStyle 的这些值:

主题:ThemeOverlay.Material.Dialog

datePickerStyle: Widget.Material.Light.DatePicker

buttonStyle: Widget.Material.Light.Button


这有点帮助,但我们仍然没有改变正面和负面的按钮样式。如果我们查看source for DatePickerDialog,我们可以看到它扩展了AlertDialog。这使事情变得更加困难,因为您需要在主题中设置自定义样式,这将影响所有 AlertDialog 按钮。如果您需要有关如何更改 buttonStyle 的示例,请发表评论。

更好的方法是在对话框可见后设置正面和负面按钮的样式。例如,在您的DialogFragment 中,您可以在onStart() 中放置以下代码来设置按钮样式:

@Override
public void onStart() 
    super.onStart();
    DatePickerDialog dialog = (DatePickerDialog) getDialog();
    Button btnPos = dialog.getButton(DatePickerDialog.BUTTON_POSITIVE);
    Button btnNeg = dialog.getButton(DatePickerDialog.BUTTON_NEGATIVE);

    /* customize the buttons here */
    btnPos.setText("CUSTOM");
    btnPos.setTextAppearance(android.R.style.TextAppearance_Large);
    btnNeg.setTextColor(Color.RED);


结论:

您可以在其他视图上使用上述方法来查找适用于该视图的样式。在 Android 上为小部件设置样式仍然是一个痛苦。您可能需要不时深入研究源代码和 XML。

【讨论】:

这很有帮助,我从中学到了一些有用的东西。它没有完全回答我的主要问题,即如何找到适用于给定视图的属性。我注意到,通过在代码中包含android.R.attr.datePickerStyle,您依赖于您已经知道的内容,但对我来说,问题是这些知识的来源。维克拉姆在评论中提到的回答实际上几乎涵盖了我需要知道的内容。赏金对我来说已经达到了它的目的,所以即使不接受你的回答,我也会奖励它。 @Cris 我很高兴这个答案很有帮助。除非您深入研究源代码,否则我认为不可能找到视图具有的属性。如果我找到更好的方法,我会更新我的答案。谢谢。

以上是关于有没有一种通用的方法可以找到适用于视图的样式?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 3D 阴影边框设置 UITextView 样式?

linux怎么查看一个文件夹的大小

带有表格视图的视图仅适用于默认视图控制器

有没有办法将变量传递给 Django 中的通用视图?

有没有一种通用的方法可以在 linux 上设置壁纸?

调用适用于矩阵或向量的行的通用代码