2022年11月30日水曜日
2022年4月14日木曜日
WindowInsetsControllerCompat を使って status bar と navigation bar の light mode を切り替える
Material Catalog アプリのコードを読んでいて見つけたんですが、
WindowCompat.getInsetsController() で取得した WindowInsetsControllerCompat の setAppearanceLightStatusBars() と setAppearanceLightNavigationBars() を使うことで、status bar と navigation bar の light mode(light mode だとアイコンがグレーになり、dark だと白になる)をコードから切り替えることができます。
このようにアプリ用の MaterialTheme のところで SideEffect を使って切り替え処理をすると、Theme の xml で頑張らなくて良くなるので便利です。
WindowCompat.getInsetsController() で取得した WindowInsetsControllerCompat の setAppearanceLightStatusBars() と setAppearanceLightNavigationBars() を使うことで、status bar と navigation bar の light mode(light mode だとアイコンがグレーになり、dark だと白になる)をコードから切り替えることができます。
このようにアプリ用の MaterialTheme のところで SideEffect を使って切り替え処理をすると、Theme の xml で頑張らなくて良くなるので便利です。
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val view = LocalView.current
val context = LocalContext.current
SideEffect {
val controller = WindowCompat.getInsetsController(context.findActivity().window, view)
controller?.isAppearanceLightStatusBars = !darkTheme
controller?.isAppearanceLightNavigationBars = !darkTheme
}
MaterialTheme(
colors = if (!darkTheme) LightColorPalette else DarkColorPalette,,
typography = Typography,
shapes = Shapes,
content = content
)
}
private tailrec fun Context.findActivity(): Activity =
when (this) {
is Activity -> this
is ContextWrapper -> this.baseContext.findActivity()
else -> throw IllegalArgumentException("Could not find activity!")
}
2020年11月19日木曜日
MaterialAlertDialogBuilder のボタンの色を変更する
non-Bridge なテーマで MaterialAlertDialogBuilder を使うと、ダイアログのボタンの色は colorPrimary になります。
そのため colorPrimary に黒っぽい色を指定した DayNight テーマだと、Dark Mode のときにボタンの文字が見えないという状態になってしまいます。
DayNight テーマの colorPrimary は変えずに Dark Mode のときだけダイアログのボタンの色を変えるには、materialAlertDialogTheme 属性を指定します。
res/values/themes.xml
そのため colorPrimary に黒っぽい色を指定した DayNight テーマだと、Dark Mode のときにボタンの文字が見えないという状態になってしまいます。
<resources>
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">#212121</item>
</style>
</resources>
DayNight テーマの colorPrimary は変えずに Dark Mode のときだけダイアログのボタンの色を変えるには、materialAlertDialogTheme 属性を指定します。
res/values/themes.xml
<resources>
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorPrimary">#212121</item>
<item name="materialAlertDialogTheme">@style/ThemeOverlay.MyApp.MaterialAlertDialog</item>
</style>
<style name="ThemeOverlay.MyApp.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog" />
</resources>
res/values-night-v8/themes.xml
<resources>
<style name="ThemeOverlay.MyApp.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="colorPrimary">#ffffff</item>
</style>
</resources>
2020年10月21日水曜日
DevFest 2020 で Material Design Components のカスタマイズについて話してきました。
資料はこちらです。
Android Studio 4.1 についてと、まとめの後のおまけにいくつかページを追加しています。
MDC をカスタマイズするときは便利だと思うので、是非参考にしてください。
2020年3月11日水曜日
dialogCornerRadius でダイアログの角丸具合を指定する
Android Pie(API Level 28)から ?android:attr/dialogCornerRadius でダイアログの角丸具合を指定できるようになりましたが、AppCompat や MaterialComponents では ?attr/dialogCornerRadius としてバックポートされています。
<item name="dialogCornerRadius">12dp</item>
API Level 21
API Level 27
API Level 28
<item name="android:dialogCornerRadius">12dp</item>
API Level 21
API Level 27
API Level 28
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="dialogCornerRadius">12dp</item>
</style>
(<item name="android:dialogCornerRadius">12dp</item> だと Android Pie(API Level 28)以降だけ角丸になります。)
<item name="dialogCornerRadius">12dp</item>
API Level 21
API Level 27
API Level 28
<item name="android:dialogCornerRadius">12dp</item>
API Level 21
API Level 27
API Level 28
2020年3月10日火曜日
Material Design Components for Android 1.1.0 でボタンのデフォルトカラーが colorAccent から colorPrimary に変わった
Theme.AppCompat.Light.DarkActionBar
Theme.MaterialComponents.Light.DarkActionBar (1.0.0)
Theme.MaterialComponents.Light.DarkActionBar (1.1.0)
何もしてないのに(MDC の version を 1.1.0 に上げたけど...) 色が!変わった!
ピンクはどこの色かというと colorAccent に指定している色です。では緑はどこの色かというと colorPrimary に指定している色です。
ボタン系のデフォルトカラーが 1.1.0 から colorPrimary に変わったようです。
AlertDialog のボタンの色は
?attr/materialAlertDialogTheme に指定されている
ThemeOverlay.MaterialComponents.MaterialAlertDialog
↓
Base.ThemeOverlay.MaterialComponents.MaterialAlertDialog
↓
Base.V14.ThemeOverlay.MaterialComponents.MaterialAlertDialog の
Widget.MaterialComponents.Button.TextButton.Dialog の
@color/mtrl_text_btn_text_color_selector
ちなみに 1.0.0 のときの @color/mtrl_text_btn_text_color_selector では colorAccent 使ってます。
ボタンの色を変えたいときは 「AlertDialog の Negative ボタンの文字色を変える」 と同じ感じでやればOK
Theme.MaterialComponents.Light.DarkActionBar (1.0.0)
Theme.MaterialComponents.Light.DarkActionBar (1.1.0)
何もしてないのに(MDC の version を 1.1.0 に上げたけど...) 色が!変わった!
ピンクはどこの色かというと colorAccent に指定している色です。では緑はどこの色かというと colorPrimary に指定している色です。
ボタン系のデフォルトカラーが 1.1.0 から colorPrimary に変わったようです。
AlertDialog のボタンの色は
?attr/materialAlertDialogTheme に指定されている
ThemeOverlay.MaterialComponents.MaterialAlertDialog
↓
Base.ThemeOverlay.MaterialComponents.MaterialAlertDialog
↓
Base.V14.ThemeOverlay.MaterialComponents.MaterialAlertDialog の
<item name="buttonBarPositiveButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog</item>
<item name="buttonBarNegativeButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog</item>
<item name="buttonBarNeutralButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush</item>
↓
Widget.MaterialComponents.Button.TextButton.Dialog の
<item name="android:textColor">@color/mtrl_text_btn_text_color_selector</item>
↓
@color/mtrl_text_btn_text_color_selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="1.00" android:color="?attr/colorPrimary" .../>
<item android:alpha="0.60" android:color="?attr/colorOnSurface" .../>
<item android:alpha="1.00" android:color="?attr/colorPrimary" .../>
<item android:alpha="0.38" android:color="?attr/colorOnSurface"/>
</selector>
あー、colorPrimary と colorOnSurface になったのねぇ。
ちなみに 1.0.0 のときの @color/mtrl_text_btn_text_color_selector では colorAccent 使ってます。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccent" android:state_enabled="true"/>
<item android:color="@color/mtrl_btn_text_color_disabled"/>
</selector>
ボタンの色を変えたいときは 「AlertDialog の Negative ボタンの文字色を変える」 と同じ感じでやればOK
<style name="ThemeOverlay.MyApp.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="buttonBarPositiveButtonStyle">@style/Widget.MyApp.Button.TextButton.Dialog</item>
<item name="buttonBarNegativeButtonStyle">@style/Widget.MyApp.Button.TextButton.Dialog</item>
</style>
<style name="Widget.MyApp.Button.TextButton.Dialog" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">#1565C0</item>
</style>
AlertDialog.Builder(this, R.style.ThemeOverlay_MyApp_MaterialAlertDialog)
.setTitle("Title")
.setMessage("Message")
.setPositiveButton(android.R.string.ok, null)
.setNegativeButton(android.R.string.cancel, null)
.show()
2020年3月9日月曜日
Material Design Components for Android 1.1.0 から Checkbox で android:button を指定するなら app:useMaterialThemeColors="false" も必要(なことが多い)
Checkbox のマークをカスタマイズするときは android:button に drawable resource を指定します。
例えば以下のような drawable を用意して Checkbox の android:button に指定したのが次のスクリーンショットの下2つです。
全く同じコードで Activity の theme を Material Design Components for Android 1.0.0 に変えたのが次のスクリーンショットです。
同じようになってますね。
全く同じコードで Activity の theme を Material Design Components for Android 1.1.0 に変えたのが次のスクリーンショットです。
なんということでしょう!android:button で指定した drawable resource が Material Design の theme color で tint されるようになりました。tint で使われる色は colorControlActivated と colorOnSurface です。
この挙動を止めるには app:useMaterialThemeColors="false" を指定します。
tint されなくなりました!
例えば以下のような drawable を用意して Checkbox の android:button に指定したのが次のスクリーンショットの下2つです。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="7dp"
android:left="7dp"
android:right="7dp"
android:top="7dp">
<selector>
<item android:state_checked="true">
<shape android:shape="oval">
<size
android:width="18dp"
android:height="18dp" />
<stroke
android:width="6dp"
android:color="#6666ff" />
</shape>
</item>
<item>
<shape android:shape="oval">
<size
android:width="18dp"
android:height="18dp" />
<stroke
android:width="2dp"
android:color="#cccccc" />
</shape>
</item>
</selector>
</item>
</layer-list>
<CheckBox
...
android:button="@drawable/checkbox"
... />
全く同じコードで Activity の theme を Material Design Components for Android 1.0.0 に変えたのが次のスクリーンショットです。
同じようになってますね。
全く同じコードで Activity の theme を Material Design Components for Android 1.1.0 に変えたのが次のスクリーンショットです。
なんということでしょう!android:button で指定した drawable resource が Material Design の theme color で tint されるようになりました。tint で使われる色は colorControlActivated と colorOnSurface です。
この挙動を止めるには app:useMaterialThemeColors="false" を指定します。
<CheckBox
...
android:button="@drawable/checkbox"
app:useMaterialThemeColors="false"
... />
tint されなくなりました!
2015年3月10日火曜日
Material Design Color メモ
| Components | alpha | color | color resource |
|---|---|---|---|
| text | 87% | #000000 | #de000000 |
| subheader | 54% | #000000 or primary color | #8a000000 |
| hint | 50% | #000000 | #80000000 |
| divider | 12% | #000000 | #1f000000 |
EditText
| state | alpha | color | color resource |
|---|---|---|---|
| error | 100% | #f44336 | #fff44336 |
| hint text | 26% | #000000 | #43000000 |
ちなみに colors_material.xml では次のように定義されている
<color name="primary_text_default_material_light">#de000000</color>
<color name="secondary_text_default_material_light">#8a000000</color>
2015年1月13日火曜日
AppCompat v7 で tint 処理しているクラスとか
メモ
- http://tools.oesf.biz/android-5.0.1_r1.0/xref/frameworks/support/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
- http://tools.oesf.biz/android-5.0.1_r1.0/xref/frameworks/support/v7/appcompat/src/android/support/v7/internal/widget/TintDrawableWrapper.java
- http://tools.oesf.biz/android-5.0.1_r1.0/xref/frameworks/support/v7/appcompat/src/android/support/v7/internal/widget/DrawableWrapper.java
- http://tools.oesf.biz/android-5.0.1_r1.0/xref/frameworks/support/v7/appcompat/src/android/support/v7/internal/widget/TintResources.java
- http://tools.oesf.biz/android-5.0.1_r1.0/xref/frameworks/support/v7/appcompat/src/android/support/v7/internal/widget/TintTypedArray.java
Android 5.0 で EditText の normal 時の色を独自に変える
以前のエントリ「Android 5.0 でのカラーカスタマイズと属性名の関係」で書いたように、EditText の normal 時の線の色は colorControlNormal になります。
colorControlNormal にはデフォルトでは textColorSecondary が指定されており、Theme.Material では @color/secondary_text_material_dark、Theme.Material.Light では @color/secondary_text_material_light になります。
これらの normal 時の色は最終的に以下になります。
実際にこの色の EditText を配置してみると、Material Design の Components > Text fields で例としてあげられている画像の色より、かなり濃いことがわかります。
colorControlNormal に薄いグレーを指定すれば、EditText の normal 時の色を変えられますが、この属性はさまざまなところで使われており、例えば CheckBox の normal 時の色も薄くなってしまいます。
colorControlNormal ではなく独自に色を指定したい場合、残念ながら用意されている属性値ではできません。 EditText の背景を独自のリソースに変える必要があります。
EditText の 5.0 でのデフォルト背景は次のようになっています。
android:drawable/edit_text_material.xml
これを参考に、AppCompat の画像リソースを利用して次のようにします。
drawable-v21/my_edit_text_material.xml
values/attr.xml
colorControlNormal にはデフォルトでは textColorSecondary が指定されており、Theme.Material では @color/secondary_text_material_dark、Theme.Material.Light では @color/secondary_text_material_light になります。
これらの normal 時の色は最終的に以下になります。
#b3ffffff
#8a000000
つまり、Theme.Material.Light では線の色は #8a000000 です。
実際にこの色の EditText を配置してみると、Material Design の Components > Text fields で例としてあげられている画像の色より、かなり濃いことがわかります。
colorControlNormal に薄いグレーを指定すれば、EditText の normal 時の色を変えられますが、この属性はさまざまなところで使われており、例えば CheckBox の normal 時の色も薄くなってしまいます。
colorControlNormal ではなく独自に色を指定したい場合、残念ながら用意されている属性値ではできません。 EditText の背景を独自のリソースに変える必要があります。
EditText の 5.0 でのデフォルト背景は次のようになっています。
android:drawable/edit_text_material.xml
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:inset="@dimen/control_inset_material">
<ripple android:color="?attr/colorControlActivated">
<item>
<selector>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
android:tint="?attr/colorControlNormal"
android:alpha="?attr/disabledAlpha" />
</item>
<item>
<nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
android:tint="?attr/colorControlNormal" />
</item>
</selector>
</item>
<item android:id="@+id/mask" android:drawable="@drawable/textfield_activated_mtrl_alpha" />
</ripple>
</inset>
これを参考に、AppCompat の画像リソースを利用して次のようにします。
drawable-v21/my_edit_text_material.xml
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:inset="@dimen/control_inset_material">
<ripple android:color="?attr/colorControlActivated">
<item>
<selector>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/abc_textfield_default_mtrl_alpha"
android:tint="?attr/colorEditTextNormal"
android:alpha="?android:attr/disabledAlpha" />
</item>
<item>
<nine-patch android:src="@drawable/abc_textfield_default_mtrl_alpha"
android:tint="?attr/colorEditTextNormal" />
</item>
</selector>
</item>
<item android:id="@android:id/mask" android:drawable="@drawable/abc_textfield_activated_mtrl_alpha" />
</ripple>
</inset>
ここでは、?attr/colorControlNormal の代わりに ?attr/colorEditTextNormal を指定しています。
values/attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="colorEditTextNormal" format="color|reference" />
</resources>
values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="editTextBackground">@drawable/my_edit_text_material</item>
<item name="colorEditTextNormal">#1f000000</item>
</style>
</resources>
Material Design の Resources > Sticker sheets & icons で配布されている stickersheet_general.ai では、EditText の色は divider と同じ #000000 の alpha 12% でした。
Android 5.0 でのカラーカスタマイズと属性名の関係
CheckBox
RadioButton
Switch
thumb
track
RatingBar
ratingbar_full_filled_material.xml
EditText
Text選択
text_select_handle_left_material.xml
text_select_handle_middle_material.xml
text_select_handle_right_material.xml
Button
ベース
btn_borderless_material.xml
ToggleButton
ベース
ProgressBar
Horizontal
SeekBar
scrubber_control_material_anim.xml
scrubber_progress_horizontal_material.xml
Spinner
ScrollBar
FastScroll
thumb
track
TimePicker のヘッダー
ExpandableListView
selectableItemBackground
item_background_borderless_material.xml
■ 参考
- normal : colorControlNormal
- checked: colorControlActivated
RadioButton
- normal : colorControlNormal
- checked: colorControlActivated
Switch
thumb
- normal : colorSwitchThumbNormal
- checked: colorControlActivated
track
- normal : colorForeground, alpha=0.3
- checked: colorControlActivated, alpha=0.3
RatingBar
- normal : colorControlNormal
- pressed: colorControlActivated
ratingbar_full_filled_material.xml
EditText
- normal : colorControlNormal
- focused: colorControlActivated
Text選択
- ハンドル : colorControlActivated
- カーソル : colorControlActivated
text_select_handle_left_material.xml
text_select_handle_middle_material.xml
text_select_handle_right_material.xml
Button
ベース
- normal : colorButtonNormal
- pressed : colorControlHighlight
btn_borderless_material.xml
ToggleButton
ベース
- normal : colorButtonNormal
- pressed : colorControlHighlight
- normal : colorControlNormal
- checked: colorControlActivated
ProgressBar
- くるくる : colorControlActivated
Horizontal
- ベース : colorControlNormal, alpha=disabledAlpha
- Progress : colorControlActivated
- SecondaryProgress : colorControlActivated, alpha=disabledAlpha
SeekBar
- ベース : colorControlNormal
- Progress : colorControlActivated
- 取手 : colorControlActivated
scrubber_control_material_anim.xml
scrubber_progress_horizontal_material.xml
Spinner
- normal : colorControlNormal
- pressed : colorControlActivated
- checked : colorControlActivated
ScrollBar
- handle : colorControlNormal
FastScroll
thumb
- normal : colorControlNormal
- pressed : colorControlActivated
track
- 常時 : colorControlNormal
TimePicker のヘッダー
- normal : colorAccent
- pressed: colorControlHighlight
ExpandableListView
- expander : colorControlNormal
selectableItemBackground
- pressed: colorControlHighlight
item_background_borderless_material.xml
■ 参考
<style name="Theme.Material">
...
<!-- Color palette -->
<item name="colorPrimaryDark">@color/primary_dark_material_dark</item>
<item name="colorPrimary">@color/primary_material_dark</item>
<item name="colorAccent">@color/accent_material_dark</item>
<item name="colorEdgeEffect">?attr/colorPrimary</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlActivated">?attr/colorAccent</item>
<item name="colorControlHighlight">@color/ripple_material_dark</item>
<item name="colorButtonNormal">@color/btn_default_material_dark</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
</style>
<style name="Theme.Material.Light" parent="Theme.Light">
...
<!-- Color palette -->
<item name="colorPrimaryDark">@color/primary_dark_material_light</item>
<item name="colorPrimary">@color/primary_material_light</item>
<item name="colorAccent">@color/accent_material_light</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlActivated">?attr/colorAccent</item>
<item name="colorControlHighlight">@color/ripple_material_light</item>
<item name="colorButtonNormal">@color/btn_default_material_light</item>
<item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
</style>
- support/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
- support/v7/appcompat/src/android/support/v7/internal/widget/TintDrawableWrapper.java
2015年1月2日金曜日
Theme.Material の SeekBar は setProgress() で
secondaryProgress の描画が消えてしまう
SeekBar は ProgressBar を継承しているので、setSecondaryProgress() で2番目のプログレスを設定することができます。
下記の動画は setSecondaryProgress() を呼んだ後に setProgress() を呼んだものです。
Holo テーマのスタイルの SeekBar(一番上)では、setProgress() を呼ぶと secondary progress のバーの描画はそのままで progress のバーがセットされます。
一方、Material テーマのスタイルの SeekBar(真ん中)では、setProgress() を呼ぶと secondary progress のバーの描画が消えてしまいます。ちなみにこの時点で getSecondaryProgress() を呼ぶと、描画は消えていますがセットされている値が返ってきます。
Material テーマのスタイルの ProgressBar(一番下)では、secondary progress のバーの描画は消えません。
そこで、SeekBar に style="@android:style/Widget.Material.ProgressBar.Horizontal" を指定してみたところ、Progress Bar と同じような見た目になり、secondary progress のバーの描画は消えなくなりました。
@android:drawable/scrubber_progress_horizontal_material
なぜ selector の中に入れると描画が変になるのかよくわかりませんが、style="@android:style/Widget.Material.ProgressBar.Horizontal" を指定するのが手っ取り早そうです。
下記の動画は setSecondaryProgress() を呼んだ後に setProgress() を呼んだものです。
Holo テーマのスタイルの SeekBar(一番上)では、setProgress() を呼ぶと secondary progress のバーの描画はそのままで progress のバーがセットされます。
一方、Material テーマのスタイルの SeekBar(真ん中)では、setProgress() を呼ぶと secondary progress のバーの描画が消えてしまいます。ちなみにこの時点で getSecondaryProgress() を呼ぶと、描画は消えていますがセットされている値が返ってきます。
Material テーマのスタイルの ProgressBar(一番下)では、secondary progress のバーの描画は消えません。
そこで、SeekBar に style="@android:style/Widget.Material.ProgressBar.Horizontal" を指定してみたところ、Progress Bar と同じような見た目になり、secondary progress のバーの描画は消えなくなりました。
<SeekBar
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Widget.Material.ProgressBar.Horizontal は次のようになっており、progressDrawable の指定が作用していると予想しました。
<style name="Widget.Material.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
<item name="progressDrawable">@drawable/progress_horizontal_material</item>
<item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material</item>
<item name="minHeight">16dip</item>
<item name="maxHeight">16dip</item>
</style>
そこで、@android:drawable/progress_horizontal_material をプロジェクト内に持ってきて次のように指定したところ、secondary progress のバーの描画は消えなくなりました。
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/progress_horizontal_material" />
progress_horizontal_material.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<nine-patch android:src="@drawable/progress_mtrl_alpha"
android:tint="?attr/colorControlNormal"
android:alpha="?android:attr/disabledAlpha" />
</item>
<item android:id="@android:id/secondaryProgress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/progress_mtrl_alpha"
android:tint="?attr/colorControlActivated"
android:alpha="?android:attr/disabledAlpha" />
</scale>
</item>
<item android:id="@android:id/progress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/progress_mtrl_alpha"
android:tint="?android:attr/colorControlActivated" />
</scale>
</item>
</layer-list>
Material テーマの SeekBar のデフォルトスタイルは Widget.Material.SeekBar です。このスタイルでは progressDrawable に @android:drawable/scrubber_progress_horizontal_material が指定されています。
<style name="Widget.Material.SeekBar">
<item name="indeterminateOnly">false</item>
<item name="progressDrawable">@drawable/scrubber_progress_horizontal_material</item>
<item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_material</item>
<item name="thumb">@drawable/scrubber_control_material_anim</item>
<item name="splitTrack">true</item>
<item name="focusable">true</item>
<item name="paddingStart">16dip</item>
<item name="paddingEnd">16dip</item>
<item name="mirrorForRtl">true</item>
<item name="background">?attr/selectableItemBackgroundBorderless</item>
</style>
scrubber_progress_horizontal_material.xml は progress_horizontal_material.xml と違い、ルートタグが <selector> です。
@android:drawable/scrubber_progress_horizontal_material
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false">
<nine-patch android:src="@drawable/scrubber_track_mtrl_alpha"
android:tint="?attr/colorControlNormal" />
</item>
<item>
<layer-list>
<item android:id="@id/background">
<nine-patch android:src="@drawable/scrubber_track_mtrl_alpha"
android:tint="?attr/colorControlNormal" />
</item>
<item android:id="@id/secondaryProgress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
android:tint="?attr/colorControlNormal" />
</scale>
</item>
<item android:id="@id/progress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
android:tint="?attr/colorControlActivated" />
</scale>
</item>
</layer-list>
</item>
</selector>
これの <layer-list> 部分だけを取り出して progressDrawable に指定したところ、secondary progress のバーの描画が消えなくなりました。なぜ selector の中に入れると描画が変になるのかよくわかりませんが、style="@android:style/Widget.Material.ProgressBar.Horizontal" を指定するのが手っ取り早そうです。
2014年12月19日金曜日
Android AlertDialog のボタンの色を変える Material Design 編
■ Lollipop
values/styles.xml
■ AppCompat
values/styles.xml
values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.Material.Light.DarkActionBar">
<item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>
<style name="AlertDialogTheme" parent="Theme.Material.Light.Dialog">
<item name="android:colorAccent">#61a00e</item>
</style>
</resources>
■ AppCompat
values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppThemeBase" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
</resources>
values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="AppThemeBase">
<item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>
<style name="AlertDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#61a00e</item>
</style>
</resources>
2014年12月10日水曜日
MaterialTabHost つくりました。
「Android Material Design のタブの仕様まとめ」の Fixed Tabs の3つの種類を簡単に実装できる MaterialTabHost を作りました。
github : yanzm/MaterialTabHost
MaterialTabHost.Type.FullScreenWidth
MaterialTabHost.Type.Centered
MaterialTabHost.Type.LeftOffset
MaterialTabHost.Type.FullScreenWidth
MaterialTabHost.Type.Centered
MaterialTabHost.Type.LeftOffset
2014年12月9日火曜日
Android Material Design な TabHost + ViewPager に移行する
前回のエントリ「Android Material Design のタブの仕様まとめ」で紹介した Material Design の Fixed Tabs full-screen width を TabHost で実装してみます。
Activity 生成ウィザードの Tabbed Activity で Swipe Views(ViewPager)を選択して作成される Activity に付け足していきます。
*以下の例は minSdkVersion = 21 としています。
0. テーマに色をセット
メインカラーとアクセントカラーをセットしておきます
res/values-v21/styles.xml
1. 普通に TabHost を実装する
基本的なタブ機能が実装できましたが、Material Design に沿ったタブにするにはいくつか修正が必要です。
2. タブ間の区切り線を消す
3. Action Bar と タブの間の影を消す
4. タブの下に影を出す
5. タブの文字を仕様に合わせる
res/color/tab_widget_text.xml
6. ViewPager のスクロールに応じてインディケータもスクロールさせる
Activity 生成ウィザードの Tabbed Activity で Swipe Views(ViewPager)を選択して作成される Activity に付け足していきます。
*以下の例は minSdkVersion = 21 としています。
0. テーマに色をセット
メインカラーとアクセントカラーをセットしておきます
res/values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:colorPrimaryDark">#00695C</item>
<item name="android:colorPrimary">#00897B</item>
<item name="android:colorAccent">#FFD54F</item>
</style>
</resources>
1. 普通に TabHost を実装する
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
tools:context=".MainActivity">
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/colorPrimary">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp" />
</TabHost>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
tabHost.setup();
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
tabHost.addTab(tabHost
.newTabSpec(String.valueOf(i))
.setIndicator(mSectionsPagerAdapter.getPageTitle(i))
.setContent(android.R.id.tabcontent));
}
tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged(String tabId) {
mViewPager.setCurrentItem(Integer.valueOf(tabId));
}
});
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
tabHost.setCurrentTab(position);
}
});
}
基本的なタブ機能が実装できましたが、Material Design に沿ったタブにするにはいくつか修正が必要です。
- タブ間の区切り線を消す
- Action Bar と タブの間の影を消す
- タブの下に影を出す
- タブの文字を仕様に合わせる
- ViewPager のスクロールに応じてインディケータもスクロールさせる
2. タブ間の区切り線を消す
@Override
protected void onCreate(Bundle savedInstanceState) {
...
TabWidget tabWidget = (TabWidget) findViewById(android.R.id.tabs);
// タブ間の区切り線を消す
tabWidget.setStripEnabled(false);
tabWidget.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE);
}
3. Action Bar と タブの間の影を消す
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Action Bar と タブの間の影を消す
getActionBar().setElevation(0);
}
4. タブの下に影を出す
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// タブの下に影を出す
// App bar の elevation は 4dp
// http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html#objects-in-3d-space-elevation
float elevation = 4 * getResources().getDisplayMetrics().density;
tabHost.setElevation(elevation);
}
5. タブの文字を仕様に合わせる
res/color/tab_widget_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#ffffffff" android:state_selected="true" />
<item android:color="#99ffffff" />
</selector>
res/layout/tab_widget.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="bottom|center_horizontal"
android:paddingBottom="16dp"
android:textColor="@color/tab_widget_text"
android:textSize="14sp"
tools:layout_width="match_parent"
tools:text="group 1 ITEM TWO" />
@Override
protected void onCreate(Bundle savedInstanceState) {
...
LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
TextView tv = (TextView) inflater.inflate(R.layout.tab_widget, tabWidget, false);
tv.setText(mSectionsPagerAdapter.getPageTitle(i));
tabHost.addTab(tabHost
.newTabSpec(String.valueOf(i))
.setIndicator(tv)
.setContent(android.R.id.tabcontent));
}
...
}
6. ViewPager のスクロールに応じてインディケータもスクロールさせる
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
tools:context=".MainActivity">
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/colorPrimary">
...
<View
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_gravity="bottom"
android:background="?android:attr/colorControlActivated" />
</TabHost>
...
</LinearLayout>
View indicator;
TabWidget tabWidget;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
tabWidget = (TabWidget) findViewById(android.R.id.tabs);
...
indicator = findViewById(R.id.indicator);
mViewPager.setOnPageChangeListener(new PageChangeListener());
}
private class PageChangeListener implements ViewPager.OnPageChangeListener {
private int scrollingState = ViewPager.SCROLL_STATE_IDLE;
@Override
public void onPageSelected(int position) {
// スクロール中はonPageScrolled()で描画するのでここではしない
if (scrollingState == ViewPager.SCROLL_STATE_IDLE) {
updateIndicatorPosition(position, 0);
}
tabWidget.setCurrentTab(position);
}
@Override
public void onPageScrollStateChanged(int state) {
scrollingState = state;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateIndicatorPosition(position, positionOffset);
}
private void updateIndicatorPosition(int position, float positionOffset) {
View tabView = tabWidget.getChildTabViewAt(position);
int indicatorWidth = tabView.getWidth();
int indicatorLeft = (int) ((position + positionOffset) * indicatorWidth);
final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) indicator.getLayoutParams();
layoutParams.width = indicatorWidth;
layoutParams.setMargins(indicatorLeft, 0, 0, 0);
indicator.setLayoutParams(layoutParams);
}
}
Android Material Design のタブの仕様まとめ
Tabs - Components - Google design guidelines
http://material-design.storage.googleapis.com/publish/v_2/material_ext_publish/0Bx4BSt6jniD7OWxWU0JiNjA4Vzg/components_tabs_usage_specs1.png
■ centered
■ left offset
*Types of tabs の Fixed tabs に「Fixed tabs have equal width, based on the widest tab label.」とあるので、それに従ったのが centered、しかし隣の画像をみると Scrollable と同じようにタブによって幅が変わっているのでそれに従ったのが left offset とした。
共通の仕様
- タブの高さ : 48dp
- indicatorの高さ : 2dp
- タブ間に区切り線なし
- 文字サイズ : 14sp Roboto Medium
- 文字位置 : ベースライン = タブ下端から20dp
- 文字色 :
- 選択・非選択で同じ色 : 選択 = #ffffff、非選択 = #99ffffff
- 選択・非選択で別の色 : 選択 = indicatorの色、非選択 = 無彩色
http://material-design.storage.googleapis.com/publish/v_2/material_ext_publish/0Bx4BSt6jniD7OWxWU0JiNjA4Vzg/components_tabs_usage_specs1.png
Fixed Tabs
■ full-screen width- タブ幅 : 画面幅 / タブ数
- タブ数 : せいぜい4つまで。タブレットではタブが横に広がりすぎるので centered か left offset の方がよい
■ centered
- タブ幅 : 12dp + 最も長いラベル幅 + 12dp(タブレットでは24dp)
- タブ数 : タブ幅 x タブ数が画面幅を超えない数まで可能
- タブは中央に寄せる
■ left offset
- タブ幅 : 12dp + ラベル幅 + 12dp(タブレットでは24dp)
- タブ数 : オフセット + タブ幅の和が画面幅を超えない数まで可能
- 画面左端から選択されているタブのラベル左端までのオフセット = 72dp(タブレットでは 80dp)
*Types of tabs の Fixed tabs に「Fixed tabs have equal width, based on the widest tab label.」とあるので、それに従ったのが centered、しかし隣の画像をみると Scrollable と同じようにタブによって幅が変わっているのでそれに従ったのが left offset とした。
Scrollable
- タブ幅 : 12dp + ラベル幅 + 12dp(タブレットでは24dp)
- 画面左端から選択されているタブのラベル左端までのオフセット = 72dp(タブレットでは 80dp)
2014年12月4日木曜日
Android Activity Transitions の対象から、Navigation Bar と Status Bar を外す(Activity Transitions を実装する その2)
「Android Activity Transitions を実装する」の続きです。
Activity Transitions の対象から Navigation Bar と Status Bar を外すには、Transition.excludeTarget() を使います。
↓ 開発者オプションでアニメーションの速度をx5にしています。
Activity Transitions の対象から Navigation Bar と Status Bar を外すには、Transition.excludeTarget() を使います。
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Transition transition = new Fade();
// Navigation Bar の背景を対象から外す
transition.excludeTarget(android.R.id.navigationBarBackground, true);
// Status Bar の背景を対象から外す
transition.excludeTarget(android.R.id.statusBarBackground, true);
getWindow().setExitTransition(transition);
getWindow().setEnterTransition(transition);
↓ 開発者オプションでアニメーションの速度をx5にしています。
Android Activity Transitions を実装する
Activity Transitions のドキュメントを読んだのですが、よくわからなかったので実際に試してみました。
コードで有効にする場合
自分で transition を作るときは、これらの親クラスの Visibility を継承するのがよさそうです。
コードで指定する場合
@android:transition/explode
@android:transition/fade
@android:transition/slide
です。
テーマで指定する場合
Android Developers のドキュメントでは、引数に this しか渡していませんが、引数が1つのメソッドはありません!(2014年12月4日現在)
次のように第2引数に null を指定します。
Fade
Slide
そのためには、どの View が共通として見なせるのか指定する必要があります。
遷移前後両方のActivityで、一意の名前を指定します。
レイアウトで指定する場合は android:transitionName を使います。
以下では、それぞれの Activity のレイアウトで ImageView に android:transitionName="image" を指定しています。
遷移前(activity_main.xml)
android:transitionName に指定した名前を makeSceneTransitionAnimation() でも指定する必要があります。
android:transitionName を使わずにコードで指定することもできます。
コードで指定する場合
テーマで指定する場合
このファイルの中身は次のようになっています。
@android:transition/move
transition リソースの書き方は Transition クラスに概要があります。
例えば、@android:transition/move の <transitionSet> に android:transitionOrdering="sequential" を指定すると、各アニメーションが順番に行われます。
res/transition/custom.xml
1. window content transitions を有効にする
Activity Transitions を使うには、window content transitions を有効にする必要があります。コードで有効にする場合
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
テーマで有効にする場合
<style name="BaseAppTheme" parent="android:Theme.Material">
<item name="android:windowContentTransitions">true</item>
</style>
2. transition を指定する
切り替え時のアニメーションを指定します。用意されているクラスは Explode, Fade, Slide です。自分で transition を作るときは、これらの親クラスの Visibility を継承するのがよさそうです。
コードで指定する場合
getWindow().setExitTransition(new Explode());
Explode, Fade, Slide に対応するリソースは@android:transition/explode
@android:transition/fade
@android:transition/slide
です。
テーマで指定する場合
<style name="BaseAppTheme" parent="android:Theme.Material">
<item name="android:windowEnterTransition">@android:transition/explode</item>
<item name="android:windowExitTransition">@android:transition/explode</item>
</style>
3. ActivityOptions を指定して実行
ActivityOptions.makeSceneTransitionAnimation() を使います。Android Developers のドキュメントでは、引数に this しか渡していませんが、引数が1つのメソッドはありません!(2014年12月4日現在)
次のように第2引数に null を指定します。
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, null).toBundle());
全体としてこんな感じになります。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setExitTransition(new Explode());
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
gotoSub();
}
});
}
private void gotoSub() {
Intent intent = new Intent(this, SubActivity.class);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, null).toBundle());
}
}
Explode
Fade
Slide
4. sharedElement を指定する
遷移前の画面の一部が拡大などして、遷移後の画面の一部になるような transition が可能です。そのためには、どの View が共通として見なせるのか指定する必要があります。
遷移前後両方のActivityで、一意の名前を指定します。
レイアウトで指定する場合は android:transitionName を使います。
以下では、それぞれの Activity のレイアウトで ImageView に android:transitionName="image" を指定しています。
遷移前(activity_main.xml)
<RelativeLayout 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"
...>
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#cccccc"
android:src="@drawable/ic_launcher"
android:transitionName="image" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="go to SubActivity" />
</RelativeLayout>
遷移後(activity_sub.xml)
<RelativeLayout 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"
...>
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#cccccc"
android:src="@drawable/gopher"
android:transitionName="image" />
</RelativeLayout>
* わかりやすさのために、遷移前後の ImageView の画像を変えています。
android:transitionName に指定した名前を makeSceneTransitionAnimation() でも指定する必要があります。
public class MainActivity extends Activity {
...
private void gotoSub() {
ImageView iv = (ImageView) findViewById(R.id.image);
Intent intent = new Intent(this, SubActivity.class);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, iv, "image").toBundle());
}
}
android:transitionName を使わずにコードで指定することもできます。
public class MainActivity extends Activity {
...
private void gotoSub() {
ImageView iv = (ImageView) findViewById(R.id.image);
String sharedElementName = "image";
iv.setTransitionName(sharedElementName);
Intent intent = new Intent(this, SubActivity.class);
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, iv, sharedElementName)
.toBundle());
}
}
public class SubActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
String sharedElementName = "image";
findViewById(R.id.image).setTransitionName(sharedElementName);
}
}
5. 複数の sharedElement を指定する
複数の View を共通のエレメントとして指定することができます。
public class MainActivity extends Activity {
...
private void gotoSub() {
ImageView iv = (ImageView) findViewById(R.id.image);
String sharedElementName = "image";
iv.setTransitionName(sharedElementName);
ImageView iv2 = (ImageView) findViewById(R.id.image2);
String sharedElementName2 = "image2";
iv2.setTransitionName(sharedElementName2);
Intent intent = new Intent(this, SubActivity.class);
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this,
new Pair<View, String>(iv, sharedElementName),
new Pair<View, String>(iv2, sharedElementName2))
.toBundle());
}
}
public class SubActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub);
String sharedElementName = "image";
findViewById(R.id.image).setTransitionName(sharedElementName);
String sharedElementName2 = "image2";
findViewById(R.id.image2).setTransitionName(sharedElementName2);
}
}
6. sharedElement の transition を指定する
sharedElement の transition は setSharedElementEnterTransition() や setSharedElementExitTransition() で指定します。その他の transition には setExitTransition() や setEnterTransition() で指定したものが適用されます。コードで指定する場合
Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.custom);
getWindow().setSharedElementExitTransition(transition);
getWindow().setSharedElementEnterTransition(transition);
XMLで用意した transition リソースから Transition オブジェクトを作るには TransitionInflater を使います。
テーマで指定する場合
sharedElement のデフォルトの transition は Theme.Material で指定されており、@android:transition/move になっています。このファイルの中身は次のようになっています。
@android:transition/move
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeBounds/>
<changeTransform/>
<changeClipBounds/>
<changeImageTransform/>
</transitionSet>
changeBounds は View の大きさをアニメーションさせ、changeImageTransform は ImageView にセットされている画像サイズをアニメーションさせます。
transition リソースの書き方は Transition クラスに概要があります。
例えば、@android:transition/move の <transitionSet> に android:transitionOrdering="sequential" を指定すると、各アニメーションが順番に行われます。
res/transition/custom.xml
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
android:transitionOrdering="sequential">
<changeBounds />
<changeTransform />
<changeClipBounds />
<changeImageTransform />
</transitionSet>
おまけ: デフォルト設定
2014年7月28日月曜日
Material Design のハンバーガーアイコン
ハンバーガーアイコンは Navigation Drawer を使うときに左上に表示する三本線のアイコンのことです。
Icons - Style - Google design guidelines にも Resources - Google design guidelines にもアイコンリソースが無かったので、Icons のページにあった絵と線の太さが2dpであるという情報からハンバーガーアイコンをaiファイルに起こしました。
ちなみに設計図は次のようになります。1マスが1dpです。
画像のサイズは 48dp x 48dp で、アイコン部分は 24dp x 24dp に収まるようにします。
aiファイルも置いておきます。
Icons - Style - Google design guidelines にも Resources - Google design guidelines にもアイコンリソースが無かったので、Icons のページにあった絵と線の太さが2dpであるという情報からハンバーガーアイコンをaiファイルに起こしました。
ちなみに設計図は次のようになります。1マスが1dpです。
画像のサイズは 48dp x 48dp で、アイコン部分は 24dp x 24dp に収まるようにします。
aiファイルも置いておきます。
登録:
コメント (Atom)



