android – Change the appearance of a widget

Question:

How to change the shape of the ТеxtView element? I have text on a semi-transparent rectangular background. How can you make a rectangle a different shape?

Answer:

All View in Android have an xml attribute android:background (related method: setBackgroundResource() ), which allows you to set the desired appearance of the widget for all possible states: normal, pressed, selected, inactive, in focus, checked, etc. ( full list ).

1. In order to get the desired appearance of the widget, you need to prepare, in fact, this view itself. Two options are possible here:

  1. Image.
    The image of the appearance of the widget must be prepared in some kind of graphical editor for all the desired states: normal, pressed, inactive and others that you require (not necessarily all, those states for which the view will not be set will not be processed – visible changes in this state you won't see).
    Since our widgets are usually not predetermined sizes (that is, they can increase or decrease depending on the content located on them, specified sizes, etc.), as a rule, these images should be converted to 9-patch format (set certain areas in which the image will be stretched, adjusting to the current dimensions, as well as the area into which the content will be displayed. More details .)
    If the widget has only a fixed size, then it is enough to prepare several similar images for different screen densities. More details .
    This method is supported by the possibility of obtaining a complex look, limited only by the artist's imagination.

  2. Draw using graphical xml markup primitives. To do this, there is an xml-attribute shape (bc corresponding to the ShapeDrawable class), which allows you to draw points, lines, rectangles, ovals and some other things, as well as apply fill, gradients, shadows, and the like.
    For this method, excellent scaling, small size and some other things, like the ability to change the color dynamically. As a disadvantage, the relative simplicity of the image.

The prepared files are placed in the res/drawable/ folder, or similar ones with qualifiers, if required.

2. After the appearance is ready, we need to create a special file-selector StateList , which will regulate which images / shapes appear under certain states of the widget:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" android:drawable="@drawable/widget_pressed" />
  <item android:drawable="@drawable/widget_normal" /> 
</selector>

Here given pressing treatment ( state_pressed ) – the whole line says: if the widget is fixed by pressing (condition true – true), then set it as the background image of the widget \ shape widget_pressed . The last item is the element without any conditions – it corresponds to the normal view of the widget and will be selected when none of the states specified earlier has been fixed. Execution of the selector goes from top to bottom and will be finished when the first state found from the top matches the condition.
This file is also located in res/drawable/

If different views are not required for certain states and the widget should always look the same when touched or inactive, etc., then the creation of the selector can (and should) be skipped. Then a static, previously prepared image is used as a background using the technology described in paragraph 1.

The finishing touch is to set the selector we created (or the static background) (I called it custom_background_selector ) as the background of the widget:

<TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="custom_background_selector"
  android:padding="12dp"
  android:text="Hello" />

As a rule, if a custom view is made for a widget, then this widget is not the only one in the application – then it is logical to move the repeating attributes, including the new background, into a separate style (for example, for a button):

res / values ​​/ styles.xml

<style name="styleMyButton" parent="android:style/Widget.Button"> >
   <item name="android:background">@drawable/custom_background_selector</item>
   <item name="android:padding">12dp</item>
   <item name="android:layout_width">wrap_content</item>
   <item name="android:layout_width">wrap_content</item>
   <item name="android:textSize">24sp</item>
</style>

res/layout/my_layout.xml

<Button
       android:id="@+id/button1"
       style="@style/styleMyButton"
       android:text="@string/text_button1"/>

<Button
       android:id="@+id/button2"
       style="@style/styleMyButton"
       android:text="@string/text_button2"/>
Scroll to Top