为什么这么复杂,从code Android中设置样式样式、复杂、code、Android

2023-09-12 01:25:07 作者:意中人

如果你想c您必须做这样的事情来设置一个按钮,你从$ C $创建样式;

If you want to set the style of a Button you create from code you have to do something like this;

Button  btn  = new Button (mActivity, null, R.attr.someattribute);

在attrs.xml,你建立了一个参考

in attrs.xml, you set up a reference

<attr name="someStyleRef" format="reference"/>

在styles.xml,可以定义一个主题

In styles.xml, you define a theme

<resources>
  <style name="Theme.SomeTheme" parent="android:style/Theme.Black">
     <item name="someStyleRef">@style/someStyle</item>
  </style>
</resources>

在styles.xml鲈被定义为例如

That lates in styles.xml is defined as for example

<style name="someStyle">
        <item name="android:layout_width">2px</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:background">@drawable/actionbar_compat_separator</item>
 </style>

这个工作,这是根据我的理解,顺便从code在Android的视图设置的样式。这似乎过于复杂。按钮的第三个构造函数的参数可以很容易地接受一种风格ID R.style.XXX

This works, and this is, according to my understanding, the way to set a style on a View from code in Android. This seems overly Complex. The button's third constructor Argument could easily have accepted a style ID R.style.XXX

任何人都可以解释为什么这额外的复杂性是必要的?

Can anyone explain why this extra complexity is needed?

推荐答案

它跟周围使用视图中的Andr​​oid的鼓励方式。这不是什么样子,你正在试图做预期的做法。首先,我会解释这个机制是什么,然后建议为你的应用程序的方法。

It has to do with the encouraged patterns within Android around using Views. This isn't the intended approach for what it looks like you're trying to do. First I'll explain what this mechanism is for and then suggest an approach for your app.

第三个参数来查看构造函数,需要生成的attr资源实现视图子类时,通常使用,因为你已经证明,允许您指定一个主题属性作为参考视图的默认样式使用。如果你有一个特殊的按钮叫AwesomeButton你可能会实现这样的构造:

The third argument to View constructors that takes an attr resource is generally used when implementing View subclasses and as you've shown, lets you specify a theme attribute to use as a reference to the View's default style. If you had a special kind of button called AwesomeButton you might implement its constructors like this:

public class AwesomeButton extends Button {
    public AwesomeButton(Context context) {
        this(context, null);
    }

    public AwesomeButton(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.awesomeButtonStyle);
    }

    public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr) {
        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.AwesomeButton, defStyleAttr, 0);
        // Read AwesomeButton-specific style attributes from a
        a.recycle();
    }

    // More code
}

在Android的 LayoutInflater 膨胀的观点,它使用2个参数的构造函数的参数(背景下,AttributeSet中)。该R.attr不断被传递给3参数版本,然后下降到按钮的在超3参数的构造函数通话。这意味着按钮中规定将读取从 AwesomeButton 的默认样式封装的东西默认样式信息的主题。在Android的一些意见,从他们的父类只能在他们所使用的默认样式不同。 (按钮实际上是其中之一。)

When Android's LayoutInflater inflates views it uses the 2-argument constructor with the arguments (Context, AttributeSet). The R.attr constant is passed through to the 3-argument version and then down to Button's 3-argument constructor in the super call. This means that Button will read default styling info for the things it encapsulates from AwesomeButton's default style as specified in your theme. Some Views within Android differ from their superclass only in the default style they use. (Button is actually one of these.)

您指定的android:layout_width 安卓layout_height 在你的风格,但是这可能是有问题的。 的LayoutParams (与开头的属性布局_ )特定于父视图,而不是他们出现在视图。这就是为什么你总是预期父视图作为第二个参数传递给 LayoutInflater#膨胀 - 它告诉哪个类应该负责跨preting充气的的LayoutParams 。如果您跳过这一点,你常常会发现,你的的LayoutParams 如您所愿,并且常常被忽略彻底的不规矩。按照惯例,我们不把的LayoutParams 的风格,即使在某些特殊情况下,它的排序工作。

You specify android:layout_width and android:layout_height in your style but this can be problematic. LayoutParams (any attribute that starts with layout_) are specific to the parent view, not the view they appear on. This is why you always pass the intended parent view as the second parameter to LayoutInflater#inflate - it tells the inflater which class should be responsible for interpreting the LayoutParams. If you skip this you will often find that your LayoutParams don't behave as you expect and are often ignored outright. By convention we don't put LayoutParams in styles even though in some special cases it sort of works.

它看起来像你试图用一种风格作为一种模板。有没有理由不使用布局资源,这和指定造型呢?

It looks like you're trying to use a style as a sort of template. Is there a reason not to use a layout resource for this and specify the styling there?

final LayoutInflater inflater = LayoutInflater.from(mActivity);
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false);

RES /布局/ styled_button.xml:

res/layout/styled_button.xml:

<Button android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/my_button_background"
        [...] />