Освой Android играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Фигуры являются подмножеством Drawable-ресурсов.
Данный вид ресурсов на основе класса ShapeDrawable позволяет описывать простые геометрические фигуры, указывая их размеры, фон и контур с помощью тега <shape>.
Можно создавать ресурсы фигур на основе стандартных фигур вроде прямоугольника, эллипса, линии. Для использования ресурсов фигур нужно создать в подкаталоге res/drawable XML-файл, в котором будет присутствовать тег <shape>, который в свою очередь может содержать дочерние элементы <corners>, <gradient>, <padding>, <size>, <solid>, <stroke>.
Имя файла без расширения будет служить идентификатором (ID): R.drawable.filename в Java-коде и @[package:]drawable/filename в XML-файлах.
shape_rect.xml - Атрибут android:shape здесь необязателен: rectangle — это значение по умолчанию.
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#0377BE"/>
</shape>
</item>
</selector>
Пример с градиентным прямоугольником в качестве разделителя
Создадим файл separator.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="0"
android:centerColor="#47CF4F"
android:endColor="#000000"
android:startColor="#000000" />
</shape>
В разметке приложения добавим код:
<TextView
android:id="@+id/tvSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<View
android:layout_width="wrap_content"
android:background="@drawable/separator"
android:layout_height="1dp" />
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<View
android:layout_width="wrap_content"
android:background="@drawable/separator"
android:layout_height="3dp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
У первого разделителя ширина 1dp, у второго - 3dp. Получили красивую полоску.
У прямоугольников можно скруглить углы при помощи тега corners
rectangle_rounded_all.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#B902B0"/>
<corners android:radius="10.0dip" />
</shape>
</item>
</selector>
Можно закруглить углы по отдельности:
rectangle_rounded_some.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#EC6118"/>
<corners android:bottomRightRadius="0.1dp"
android:bottomLeftRadius="7dip"
android:topLeftRadius="7dip"
android:topRightRadius="0.1dp"/>
</shape>
</item>
</selector>
shape_oval.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#FCD366"/>
</shape>
</item>
</selector>
Другой вариант с пунктиром:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:centerColor="#FFFF00"
android:centerX="0.5"
android:centerY="0.5"
android:endColor="#00FF00"
android:gradientRadius="100"
android:startColor="#FF0000"
android:type="radial" />
<stroke
android:dashGap="6dip"
android:dashWidth="8dip"
android:width="5dip"
android:color="#000000" />
</shape>
shape_ring.xml - Для кольца имеются дополнительные атрибуты:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="ring" android:innerRadiusRatio="3"
android:thicknessRatio="5.333">
<solid android:color="#7DBE15"/>
</shape>
</item>
</selector>
shape_line.xml - Линия может быть только горизонтальной
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="line">
<stroke android:width="1dip" android:color="#F20107" />
</shape>
</item>
</selector>
Тег gradient (класс GradientDrawable) позволяет создавать сложные градиентные заливки. Каждый градиент описывает плавный переход между двумя или тремя цветами с помощью линейного/радиального алгоритма или же используя метод развертки.
Тег gradient внутри тега shape. Основные атрибуты: type, startColor (обязателен), endColor (обязателен) и middleColor (необязателен). Также иногда оказывается полезным атрибут centerColor.
Используя атрибут type, вы можете описать свой градиент:
gradient_linear.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient android:type="linear" android:endColor="#3C0000" android:startColor="#FF0202" android:angle="45.0" />
<corners android:radius="10.0dip" />
</shape>
</item>
</selector>
Дополнительный материал: Android Dev Tip #3 - помните о прозрачности, который может привести к другому результату.
Также можно задействовать атрибуты centerX и centerY.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="@android:color/white"
android:centerColor="@android:color/holo_blue_dark"
android:endColor="@android:color/black"
android:centerY="0.2" />
</shape>
gradient_radial.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient android:type="radial" android:endColor="#3C0000" android:startColor="#FF0202" android:gradientRadius="50"/>
<corners android:radius="10.0dip" />
</shape>
</item>
</selector>
Интересный эффект получается при использовании множества радиальных градиентов.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:layout_height="wrap_content">
<solid android:color="@android:color/black" />
</shape></item>
<item><shape>
<gradient
android:type="radial"
android:gradientRadius="100%"
android:startColor="@android:color/holo_purple"
android:centerX="0.1"
android:centerY="0.1"
android:endColor="@android:color/transparent" />
</shape></item>
<item><shape>
<gradient
android:type="radial"
android:gradientRadius="70%"
android:startColor="@android:color/holo_orange_light"
android:centerX="0.8"
android:centerY="0.5"
android:endColor="@android:color/transparent" />
</shape></item>
<item><shape>
<gradient
android:type="radial"
android:gradientRadius="40%"
android:startColor="@android:color/holo_blue_light"
android:centerX="0.8"
android:centerY="0.1"
android:endColor="@android:color/transparent" />
</shape></item>
<item><shape>
<gradient
android:type="radial"
android:gradientRadius="70%"
android:startColor="@android:color/holo_green_light"
android:centerX="0.2"
android:centerY="0.8"
android:endColor="@android:color/transparent" />
</shape></item>
<item><shape>
<gradient
android:type="radial"
android:gradientRadius="50%"
android:startColor="@android:color/holo_red_light"
android:centerX="0.7"
android:centerY="0.85"
android:endColor="@android:color/transparent" />
</shape></item>
</layer-list>
Рисует развёрточный градиент с помощью перехода между цветами startColor и endColor вдоль внешнего края фигуры (как правило, кольца).
Можно использовать атрибуты android:centerX и android:centerY.
gradient_sweep.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient android:type="sweep" android:endColor="#3C0000" android:startColor="#FF0202" />
<corners android:radius="10.0dip" />
</shape>
</item>
</selector>
gradient_circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:centerColor="#0f0"
android:endColor="#f00"
android:startColor="#f00"
android:type="sweep" />
<size
android:height="400dp"
android:width="400dp" />
</shape>
Попробуйте также такой вариант.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item><shape>
<solid android:color="@android:color/black" />
</shape></item>
<item><shape>
<gradient
android:type="sweep"
android:centerX="0.3"
android:centerY="0.1"
android:startColor="@android:color/holo_red_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></item>
<item><shape>
<gradient
android:type="sweep"
android:centerX="0.8"
android:centerY="0.3"
android:startColor="@android:color/holo_blue_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></item>
<item><shape>
<gradient
android:type="sweep"
android:centerX="0.1"
android:centerY="0.5"
android:startColor="@android:color/holo_green_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></item>
<item><shape>
<gradient
android:type="sweep"
android:centerX="0.6"
android:centerY="0.7"
android:startColor="@android:color/holo_orange_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></item>
<item><shape>
<gradient
android:type="sweep"
android:centerX="0.1"
android:centerY="0.9"
android:startColor="@android:color/holo_purple"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></item>
</layer-list>
А почему бы не повращать?
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item><shape>
<solid android:color="@android:color/black" />
</shape></item>
<item><rotate android:fromDegrees="66" android:toDegrees="0" android:pivotY="50%" android:pivotX="50%"><shape>
<gradient
android:type="sweep"
android:centerX="0.3"
android:centerY="0.5"
android:startColor="@android:color/holo_red_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></rotate></item>
<item><rotate android:fromDegrees="290" android:toDegrees="0" android:pivotY="40%" android:pivotX="30%"><shape>
<gradient
android:type="sweep"
android:centerX="0.8"
android:centerY="0.3"
android:startColor="@android:color/holo_blue_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></rotate></item>
<item><rotate android:fromDegrees="18" android:toDegrees="0" android:pivotY="40%" android:pivotX="30%"><shape>
<gradient
android:type="sweep"
android:centerX="0.1"
android:centerY="0.5"
android:startColor="@android:color/holo_green_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></rotate></item>
<item><rotate android:fromDegrees="280" android:toDegrees="0" android:pivotY="50%" android:pivotX="30%"><shape>
<gradient
android:type="sweep"
android:centerX="0.6"
android:centerY="0.7"
android:startColor="@android:color/holo_orange_dark"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></rotate></item>
<item><rotate android:fromDegrees="0" android:toDegrees="0" android:pivotY="50%" android:pivotX="30%"><shape>
<gradient
android:type="sweep"
android:centerX="0.0"
android:centerY="0.0"
android:startColor="@android:color/holo_purple"
android:centerColor="@android:color/transparent"
android:endColor="@android:color/transparent"/>
</shape></rotate></item>
</layer-list>
Создадим отдельный файл res/drawable/roundrect.xml и с его помощью скруглим уголки у LinearLayout, ImageView, TextView, EditText:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="15dp" />
<gradient
android:angle="90"
android:endColor="#FFFFFFFF"
android:startColor="#FF000000"
android:type="linear" />
<stroke
android:width="1dp"
android:color="#FF000000" />
<padding
android:bottom="15dp"
android:left="15dp"
android:right="15dp"
android:top="15dp" />
</shape>
В разметке активности пишем следующее:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/roundrect"
android:orientation="vertical"
tools:context=".MainActivity" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/roundrect"
android:src="@drawable/ic_launcher"
android:contentDescription="Round Image View"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:text="Я - TextView"
tools:ignore="HardcodedText" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="@drawable/roundrect"
android:hint="EditText with roundrect"
android:text="Я - EditText"
tools:ignore="HardcodedText" />
</LinearLayout>
Результат:
В Белом доме есть Овальный кабинет. Если вам придётся писать приложение для администрации президента США, то все элементы нужно сделать овальными. Создадим файл res/drawable/oval.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<gradient
android:angle="90"
android:endColor="#FFFFFFFF"
android:startColor="#FF000000"
android:type="linear" />
<stroke
android:width="1dp"
android:color="#FF000000" />
<padding
android:bottom="15dp"
android:left="15dp"
android:right="15dp"
android:top="15dp" />
</shape>
Заменим в предыдущем примере android:background="@drawable/roundrect" на android:background="@drawable/oval".
Получим овальный интерфейс: