Question:
How to reshape a ТеxtView
element? I have text on a translucent rectangular background. How can you make a rectangle a different shape?
Answer:
All View
in Android have the android:background
xml attribute (related method: setBackgroundResource()
), which allows you to set the desired appearance of the widget for all possible states: normal, pressed, selected, inactive, focused, checked, etc. ( full list ).
1. In order to get the desired appearance of the widget, you need to prepare, in fact, this view itself. There are two options here:
-
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 – there will be no visible changes in this state you won't see).
Since our widgets usually have undefined sizes (that is, they can increase or decrease depending on the content located on them, the given sizes, etc.), then, as a rule, these images should be converted to the9-patch
format (specify certain areas in which the image will be stretched, adjusting to the current dimensions, as well as the area in which the content will be displayed.More .)
If the widget has only a fixed size, then it is enough to prepare several similar images for different screen densities. Read more .
This method is supported by the possibility of obtaining a complex look, limited only by the imagination of the artist. -
Draw using graphic primitives of xml markup. To do this, there is an xml-attribute
shape
( bc corresponding classShapeDrawable
), which allows you to draw points, lines, rectangles, ovals and some other things, as well as apply fills, gradients, shadows and the like.
For this method, excellent scaling, small size and some other things, such as the ability to change the color dynamically. As a disadvantage, the relative simplicity of the image.
Prepared files are placed in the res/drawable/
folder, or similar with qualifiers, if required.
2.After the appearance is ready, we need to create a special selector file 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>
The pressing processing is set here ( state_pressed
) – the whole line says: if the widget is pressed ( true
state), then set the image\shape widget_pressed
as the background of the widget. An unconditional element comes last – it corresponds to the normal appearance of the widget and will be selected when none of the states previously specified have been committed. Execution of the selector goes from top to bottom and will be completed when the first condition found on top matches the condition.
This file is also located in res/drawable/
If different views for certain states are not required and the widget should always look the same when touched and when inactive, etc., then creating a selector can (and should) be skipped. Then a static, pre-prepared image using the technology described in paragraph 1 is used as a background.
3.The final touch is to set the selector (or static background) we created (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 alone in the application – then it is logical to put 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"/>