18 ноября 2010

немного стиля Android виджетам!

Вчера коллега спросил, как бы поменять "эти ужасные зелёные ползунки у SeekBar'а в оболочке HTC Sense"? Сегодня я над этим немного поразмыслил, благо недавно как раз заглядывал в эту тему.
Начать, пожалуй, стоит с ознакомления со стилями Android'а. Увы, в редкой книге поднимается эта тема, так что можно почитать про стили в документации и обратить внимание на встроенные стили. Во встроенных есть, например, такой фрагмент:

<style name="Widget.SeekBar">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
<item name="android:indeterminateDrawable">@android:drawable/progress_horizontal</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
<item name="android:thumb">@android:drawable/seek_thumb</item>
<item name="android:thumbOffset">8px</item>
<item name="android:focusable">true</item>
</style>

В нём и задаётся стиль для SeekBar'а. Значит, точно так же мы можем его переопределить. Как показывает вскрытие, @android:drawable/progress_horizontal есть фигура, описанная в xml (исходник, за ленью, выковыривать не стал), сделаем свою:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="1px" android:color="#FFF" />
<corners android:radius="9dip"/>

<gradient
android:angle="270"
android:endColor="#CCE2001A"
android:startColor="#CCA10013"
android:type="linear"/>
</shape>

Красный градиент в белой рамке.
Создадим стиль для виджета:
    <style name="MySeekBar">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@drawable/seekbar</item>
<item name="android:indeterminateDrawable">@drawable/seekbar</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
<item name="android:thumbOffset">8px</item>
<item name="android:focusable">true</item>
</style>

и применим его на живом экземпляре:
<SeekBar
style="@style/MySeekBar"
android:id="@+id/screenControlVolume"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:layout_marginBottom="10dip"/>

Итог мучений (внизу - стандартный, не HTC):

Ну и, надо полагать, очевидно, что можно расширить и углубить мысль и применять этот подход почти ко всему.
UPD:
Как говорил мой завкафедры, показывая пальцем на голову, "Вы никогда не сможете перестать работать". И уже улёгшись спать, я вспомнил, что полоска-то в моём SeekBar'е одинакового цвета что слева от указателя позиции, что справа. Непорядок, который я сегодня исправляю. Итак, всё-таки расковыряв исходник android-варианта фигуры этой полоски, переписал свою версию:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<stroke android:width="1px" android:color="@color/widgetBorder" />
<corners android:radius="9dip"/>

<gradient
android:angle="270"
android:endColor="@color/widgetBorder"
android:startColor="@color/widgetBorder"
android:type="linear"/>
</shape>
</item>

<item android:id="@android:id/progress">
<clip>
<shape>
<stroke android:width="1px" android:color="@color/widgetBorder" />
<corners android:radius="9dip"/>

<gradient
android:angle="270"
android:endColor="@color/gradientWidgetEndColor"
android:startColor="@color/gradientWidgetStartColor"
android:type="linear"/>
</shape>
</clip>
</item>
</layer-list>

тут уже список слоёв с 2 (в оригинале 3, зачем третья можете подумать на досуге), в которых могут быть разные фигуры, в моём случае - всё те же скруглённые градиентные прямоугольники, верхний слой обрезан - это левая часть. Ну и вот как это выглядит в моём проекте:

Комментариев нет: