So legen Sie das Stilattribut in einer Ansicht programmgesteuert fest

107

Ich erhalte eine Ansicht aus dem XML mit dem folgenden Code:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);

Ich möchte einen "Stil" für die Schaltfläche festlegen. Wie kann ich das in Java tun, da ich für jede Schaltfläche, die ich verwenden möchte, mehrere Stile verwenden möchte?

Fussel_
quelle

Antworten:

52

Im Allgemeinen können Sie Stile nicht programmgesteuert ändern. Sie können das Aussehen eines Bildschirms, eines Teils eines Layouts oder einer einzelnen Schaltfläche in Ihrem XML-Layout mithilfe von Themen oder Stilen festlegen . Themen können jedoch programmgesteuert angewendet werden .

Es gibt auch so etwas wie ein, mit StateListDrawabledem Sie verschiedene Zeichen für jeden Zustand definieren Buttonkönnen, in dem Sie sich befinden können, ob fokussiert, ausgewählt, gedrückt, deaktiviert und so weiter.

Damit Ihre Schaltfläche beim Drücken die Farbe ändert, können Sie beispielsweise eine XML-Datei mit dem Namen " res/drawable/my_button.xmlVerzeichnis" wie folgt definieren:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:state_pressed="true"
    android:drawable="@drawable/btn_pressed" />
  <item
    android:state_pressed="false"
    android:drawable="@drawable/btn_normal" />
</selector>

Sie können diesen Selektor dann auf a anwenden, Buttonindem Sie die Eigenschaft festlegen android:background="@drawable/my_button".

Christopher Orr
quelle
4
Mein Problem ist, dass ich Daten von einem Webservice lade, die meine Schaltflächeninformationen beschreiben. Die Schaltflächen müssen je nach Kategorie einen anderen Stil haben. Deshalb möchte ich den Stil dynamisch setzen.
Lint_
3
Nun, Sie können das Android- styleAttribut nicht ändern , aber Sie können den Hintergrund eines Buttonähnlichen Programms wie bei jeder anderen Ansicht programmgesteuert festlegen , wenn dies ausreicht. Als ButtonErbe von TextViewkönnen Sie auch die Texteigenschaften ändern. Schauen Sie sich einfach die API-Dokumentation für diese Elemente an ... developer.android.com/reference/android/view/…
Christopher Orr
Ich habe gerade darüber nachgedacht, kurz bevor ich überprüft habe, ob ich neue Antworten habe. Vielen Dank.
Lint_
5
Ist es nicht möglich, einen Stil für eine Schaltfläche zu erstellen, der die Textgröße, die Ränder usw. usw. definiert, und diesen dann programmgesteuert auf eine Schaltfläche anzuwenden? Sicherlich kann man sagen, wenn ich sechs Tasten habe, die den gleichen Stil haben wollen?
Bär
Welches Attribut können wir aufblasen? Können wir die Ränder aufblasen und auffüllen?
Android Man
49

Zunächst müssen Sie keinen Layout-Inflater verwenden, um einen einfachen Button zu erstellen. Sie können einfach verwenden:

button = new Button(context);

Wenn Sie die Schaltfläche formatieren möchten, haben Sie zwei Möglichkeiten: Am einfachsten ist es, alle Elemente im Code anzugeben, wie viele der anderen Antworten vermuten lassen:

button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);

Die andere Option besteht darin, den Stil in XML zu definieren und auf die Schaltfläche anzuwenden. Im allgemeinen Fall können Sie a ContextThemeWrapperdafür verwenden:

ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);

Um die textbezogenen Attribute in einer Textansicht (oder deren Unterklassen wie Button) zu ändern, gibt es eine spezielle Methode:

button.setTextAppearance(context, R.style.MyTextStyle);

Letzteres kann nicht zum Ändern aller Attribute verwendet werden. Um beispielsweise die Polsterung zu ändern, müssen Sie a verwenden ContextThemeWrapper. Aber für Textfarbe, Größe usw. können Sie verwenden setTextAppearance.

Beetstra
quelle
1
Einfach brilliant. ContextThemeWrapper - ist das, wonach ich so lange gesucht habe.
Ayaz Alifov
Das funktioniert fantastisch. Ich habe eine Weile nach dieser Lösung gesucht.
Jasonjwwilliams
14

Ja, Sie können zum Beispiel in einer Schaltfläche verwenden

Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);
Dayerman
quelle
5
Dadurch wird der Hintergrund festgelegt, aber ein Stil kann mehr als nur einen Hintergrund angeben. Viele Ansichten (einschließlich Button) scheinen einen Konstruktor zu haben, der eine Stil-ID als Parameter verwendet. Ich habe jedoch Probleme damit, dass das für mich funktioniert - die Schaltfläche wird als Text ohne Rand oder ähnliches angezeigt. Was ich stattdessen tun könnte, ist ein Layout mit nur einer Schaltfläche (mit einem angegebenen Stil) zu erstellen, dieses Layout aufzublasen, dann den Schaltflächentext festzulegen und so weiter.
spaaarky21
11

Sie können Stilattribute wie folgt erstellen:

Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);

anstelle von:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btn"
    style="?android:attr/buttonBarButtonStyle"

    />
Kristy Welsh
quelle
7
Eine gute Antwort unter Berücksichtigung eines Buttons soll erstellt werden. Es wäre schön zu sehen, wie das für eine vorhandene Schaltfläche gemacht wird.
Qualitätskatalysator
Siehe die Antwort von cesards.
Kristy Welsh
10

Wenn Sie die Support-Bibliothek verwenden, können Sie diese einfach verwenden

TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);

für Textansichten und Schaltflächen. Es gibt ähnliche Klassen für den Rest der Ansichten :-)

cesards
quelle
Welches R-Paket benötigen Sie, um diesen Stil zu erhalten?
Htafoya
6

Für alle, die nach einer Materialantwort suchen, lesen Sie diesen SO-Beitrag: Farbschaltflächen in Android mit Material Design und AppCompat

Ich habe eine Kombination dieser Antwort verwendet, um die Standardtextfarbe der Schaltfläche für meine Schaltfläche auf Weiß festzulegen: https://stackoverflow.com/a/32238489/3075340

Dann diese Antwort https://stackoverflow.com/a/34355919/3075340 , um die Hintergrundfarbe programmgesteuert festzulegen. Der Code dafür lautet:

ViewCompat.setBackgroundTintList(your_colored_button,
 ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));

your_colored_buttonkann nur eine normale Buttonoder eine AppCompat-Schaltfläche sein, wenn Sie möchten - ich habe den obigen Code mit beiden Arten von Schaltflächen getestet und es funktioniert.

EDIT: Ich habe festgestellt, dass Pre-Lollipop-Geräte mit dem obigen Code nicht funktionieren. In diesem Beitrag erfahren Sie, wie Sie Unterstützung für Pre-Lollipop-Geräte hinzufügen: https://stackoverflow.com/a/30277424/3075340

Grundsätzlich tun Sie dies:

Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}
Mikro
quelle
6

Abhängig davon, welche Stilattribute Sie ändern möchten, können Sie möglicherweise die Pariser Bibliothek verwenden:

Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);

Viele Attribute wie Hintergrund, Auffüllen, Textgröße, Textfarbe usw. werden unterstützt.

Haftungsausschluss: Ich habe die Bibliothek verfasst.

Nathanael
quelle
5

Die Antwort von @Dayerman und @h_rules ist richtig. Um ein ausführliches Beispiel mit Code zu geben, erstellen Sie im Zeichenordner eine XML-Datei mit dem Namen button_disabled.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">   
 <solid android:color="@color/silver"/>
<corners
   android:bottomRightRadius="20dp"
   android:bottomLeftRadius="20dp"
   android:topLeftRadius="20dp"
   android:topRightRadius="20dp"/>
</shape>

Dann in Java,

((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);

Dadurch wird die Eigenschaft der Schaltfläche deaktiviert und die Farbe auf Silber gesetzt.

[Die Farbe ist in color.xml wie folgt definiert:

<resources>

    <color name="silver">#C0C0C0</color>

</resources>
biniam
quelle
4
@ Pacerier: Die Frage sagt das überhaupt nicht. Es ist nicht eindeutig, ob der Stil XML oder Java ist. Es wird nur gefragt, wie der Stil programmgesteuert festgelegt werden soll.
Harvey
3

Zur Laufzeit wissen Sie, welchen Stil Ihre Schaltfläche haben soll. Zuvor können Sie in XML im Layoutordner alle sofort einsatzbereiten Schaltflächen mit den von Ihnen benötigten Stilen bereitstellen. Im Layoutordner befindet sich möglicherweise eine Datei mit dem Namen: button_style_1.xml. Der Inhalt dieser Datei könnte folgendermaßen aussehen:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/styleOneButton"
    style="@style/FirstStyle" />

Wenn Sie mit Fragmenten arbeiten, wird diese Schaltfläche in onCreateView wie folgt aufgeblasen:

Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

Dabei ist Container der ViewGroup-Container, der der onCreateView-Methode zugeordnet ist, die Sie beim Erstellen Ihres Fragments überschreiben.

Benötigen Sie noch zwei solcher Tasten? Sie erstellen sie folgendermaßen:

Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);

Sie können diese Schaltflächen anpassen:

secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");

Anschließend fügen Sie dem Layout-Container, den Sie auch in der onCreateView-Methode aufgeblasen haben, Ihre benutzerdefinierten, stilisierten Schaltflächen hinzu:

_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);

_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);

Und so können Sie dynamisch mit stilisierten Schaltflächen arbeiten.

Jerry Frost
quelle
0

Ich habe dafür eine Hilfsschnittstelle mit dem Haltermuster erstellt.

public interface StyleHolder<V extends View> {
    void applyStyle(V view);
}

Implementieren Sie nun für jeden Stil, den Sie pragmatisch verwenden möchten, einfach die Benutzeroberfläche, zum Beispiel:

public class ButtonStyleHolder implements StyleHolder<Button> {

    private final Drawable background;
    private final ColorStateList textColor;
    private final int textSize;

    public ButtonStyleHolder(Context context) {
        TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);

        Resources resources = context.getResources();

        background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));

        textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));

        textSize = ta.getDimensionPixelSize(
                ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
                resources.getDimensionPixelSize(R.dimen.standard_text_size)
        );

        // Don't forget to recycle!
        ta.recycle();
    }

    @Override
    public void applyStyle(Button btn) {
        btn.setBackground(background);
        btn.setTextColor(textColor);
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }
}

Deklarieren Sie ein Stylable in Ihrem attrs.xml, das Stylable für dieses Beispiel lautet:

<declare-styleable name="ButtonStyleHolder">
    <attr name="android:background" />
    <attr name="android:textSize" />
    <attr name="android:textColor" />
</declare-styleable>

Hier ist der Stil deklariert in styles.xml:

<style name="button">
    <item name="android:background">@drawable/button</item>
    <item name="android:textColor">@color/light_text_color</item>
    <item name="android:textSize">@dimen/standard_text_size</item>
</style>

Und schließlich die Implementierung des Style-Inhabers:

Button btn = new Button(context);    
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);

Ich fand dies sehr hilfreich, da es leicht wiederverwendet werden kann und den Code sauber und ausführlich hält. Ich würde empfehlen, dies nur als lokale Variable zu verwenden, damit der Garbage Collector seine Arbeit erledigen kann, sobald wir alle Stile festgelegt haben .

Kostyantin2216
quelle
-1

Ich hatte kürzlich das gleiche Problem. Hier ist, wie ich es gelöst habe.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:weightSum="2"

    android:background="#FFFFFF"
    android:orientation="horizontal"
    >

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#0000FF" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#F000F0" />
    </LinearLayout>
    <!-- This is the special two colors background END-->

   <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="This Text is centered with a special backgound,
    You can add as much elements as you want as child of this RelativeLayout"
    android:textColor="#FFFFFF"
    android:textSize="20sp" />
</RelativeLayout>
  • Ich habe ein LinearLayout mit Android verwendet: weightSum = "2"
  • Ich gab den beiden untergeordneten Elementen android: layout_weight = "1" (ich gab jeweils 50% des übergeordneten Speicherplatzes (Breite & Höhe))
  • Und schließlich habe ich den beiden untergeordneten Elementen unterschiedliche Hintergrundfarben gegeben, um den endgültigen Effekt zu erzielen.

Vielen Dank !

dev242
quelle