AppCompatのテーマでAndroid2.3のサブメニューの文字と背景色が共に白で見えない件と、appcompat_v7とgoogle-play-services_libのエラー等について
えっと、AndroPainterという一番最初にうぷしたペイントアプリを、新しいSDKとAppCompatのテーマを利用して、なるべくシンプルに、可読性のよさを重視(保守性重視)して修正をしたのですが、
- ToolBarではViewの処理が煩雑になる
- Android 2.3、Gingerbreadの端末は「ハードウェアキー」があるので、フル画面で表示したい
※ ToolBarが邪魔w
ということで、
- Android 3.0以上、API Level 11、HONEYCOMB以上はActionBarでメニュー表示
- HONEYCOMB以下ではActionBarを隠し、物理キー押下でメニュー表示&利用
という仕様にしたのですが、その時にはまり、僕なりに解決 or 対策した事をメモ書き。
※ こちらがそのペイントアプリです。(クリックでGoogle Play Store別窓で開きます)
Android 2.3、Gingerbreadのサブメニューが文字と背景色が白くて見えないというバグ
このペイントアプリはメニューを表示させ、ペン先・ブラシをサブメニューで更に表示させる仕様にしてるのですが、そのサブメニューの表示の際に「文字と背景色が白くて見えない」というバグがある事が判明。
xmlファイルでこのようにメニュー内にメニューを入れて、つまるところサブメニューを作成している。
メニュー表示まではいいのだけど・・サブメニューを呼び出すと背景と文字色が白くて見えない!
サブメニューを押下するとかろうじて見えるというお粗末な仕様w
AppCompatのLightやDarcActionBar等、テーマを変更しても同様でした。
解決策としては、ピアノアプリ作成した頃には実装してたけど、メニュー自体の背景と文字色をvalue、value-v11のtheme.xlmで分けて指定する方法がシンプルに思えたけど、煩雑になり、後日また見直すの面倒なので辞めた。
また、コード上でもメニュー弄る事出来るけど、やはり煩雑になるので辞めた。
で、Android 2.3.xではサブメニューをListで表示させるクラスを作り、選択するという方法に変更しました。
onCreateOptionsMenu内でメニュー押下して、ブラシ選択する際に呼び出されるサブメニュー部分の処理をコメントアウトして、変わりにリスト表示させ、反映されるかどうか確認。
無事にリスト表示され、選択して反映されました。キャプチャのように、Build.VERSION.SDK_INTでHONEYCOMB未満だとPenList,classを呼び出してます。
ところでActivityから別Activity呼んでるけど、もうFragment使うべきですねよw
でも目的は果たせてるし、時間無いので次回修正時に利用しようかなw
因みにリストは下記の手順で押下場所をintで取得、文字通りswitchさせてますw
private void setAdapter(){
String[] str = { // String型の配列に手動でメニューの文字を代入
getString(R.string.option20),getString(R.string.option21),getString(R.string.option22),getString(R.string.option23),
getString(R.string.option24),getString(R.string.option25),getString(R.string.option26),getString(R.string.option27),
getString(R.string.option28),getString(R.string.option29),getString(R.string.option30),getString(R.string.option31)
};
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,str);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
arg1.setSelected(true); // 選択をtrue
// 引数のarg2で押下場所を取得し、値によって処理を振り分け
switch(arg2){
case 0:
MyView.mPaint.setMaskFilter(null);
finish();
break;
case 1:
MyView.mPaint.setMaskFilter(AndroPainter.mask[0]);
finish();
break;
~ 省略 ~
case 11:
MyView.changeBrush = 3;
MyView.brush = BitmapFactory.decodeResource(getResources() , R.drawable.brush_spread);
finish();
break;
} // switch
}
});
} // setAdapter()はここまで
メニューはAndroid 3.0、HONEYCOMB以上とそれ未満の端末用、2つのメニューを作り、3.0以上ではこれまで通り、サブメニューから選択する仕様にしてます。
いや、ToolBarかActionBar使えばこんなめんどくさい事する必要ないけど、ペイントアプリなので、なるべく画面広く使いたいから邪魔な部分(ツールバーですね)は排除したかったし、上述の通り、Viewの処理が煩雑になるのでこんな仕様にしてますw
※ 言わなくても分かってると思いますが、例外はあるものの、Android 3.0以降の端末では物理キーがなく、ActionBar、Toolbarにメニュー実装する仕様なので表示させてます。
※ Android 2.3.x、Gingerbreadは折角物理キーがあるのに使わない手はないでしょう。
ActionBarでタイトル、文字色、PopupMenuを設定するのは意外な事にToolBarと同じで簡単だった
AppCompatがまた更新されて仕様が変わってめんどくさくなったけど、ActionBarとToolbarのテーマ設定方法に関しては同じで、むしろ楽になった事が試行錯誤の結果分かりました。
※ 手探りだったけど、漢詩アプリの時に試行錯誤したテーマ変更方法の学習成果のおかげでクリアw
以前のActionBarのテーマ設定方法は忘れてもいいと思いますw
※ もちろん自身のアプリの仕様によりますけどね。
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="https://schemas.android.com/apk/res/android">
<style name="PinkTheme" parent="Theme.AppCompat">
<item name="colorPrimaryDark">@color/pink_500</item>
<item name="android:textColorPrimary">@color/pink_50</item>
<item name="android:windowBackground">@color/pink_50</item>
<item name="colorButtonNormal">@color/pink_500</item>
<item name="colorControlHighlight">@color/pink_100</item>
<!-- この部分、actionBarPopupThemeは2.3.xのメニューで反映されるので追加。-->
<item name="toolbarStyle">@style/PinkToolbar</item>
<item name="actionBarPopupTheme">@style/PinkToolbar</item>
<item name="windowActionModeOverlay">true</item>
</style>
<!-- ActionBarもToolBarもWidget.AppCompat.Toolbar属性のみで変更可能! -->
<style name="PinkToolbar" parent="Widget.AppCompat.Toolbar">
<item name="android:background">@color/pink_500</item>
<item name="popupTheme">@style/PopupMenu_Pink</item>
<item name="theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>
<style name="PopupMenu_Pink" parent="ThemeOverlay.AppCompat.Light">
<item name="android:background">@color/pink_500</item>
<item name="android:textColor">@color/pink_50</item>
</style>
<!-- Support library compatibility は利用しなくても大丈夫。忘れていいんじゃないw -->
</resources>
解説すると、先ず、ActionBarとToolBarのテーマ属性方法が同じという事に気が付くのに時間がかかった。
調べれば出てくるし、知ってるはずなので割愛するけど、今までの方法ではなぜかActionBarに設定が反映されず。で、もしやと思い、「ToolBar」の属性変更を試したら、そのまま反映されましたw
<style name="PinkToolbar" parent="Widget.AppCompat.Toolbar">
ついでに、2.3.xでメニューの色を反映させる方法として
<item name="actionBarPopupTheme">@style/PinkToolbar</item>
というのがテーマ内で直接指定で反映される事が分かったので利用してます。
google-play-services_libとsupport-v7-appcompat、appcompat_v7のエラーではまる
android-support-v7-appcompatの最新版をworkspaceへインポートしたら、アプリ起動直後、
~ android.support.v7.internal.widget.NativeActionModeAwareLayout ~
というエラーが出た。
本当に次から次へと意味不明なエラーが出まくりですw
Androidプログラミングには打たれても打たれても立ち上がる不屈の精神と、何よりもどれだけドロイド君を愛しているのかが試されるのではないでしょうかw
で、LogCatのエラー内容を超簡単に要約すると
setContentView(R.layout.splash);で、xmlのLayoutファイルを読み時に、appcompatの内部でエラーが出ている的な内容。
因みに他のAndroidアプリでも同様の現象が起きたので、純粋にappcompatのバグのようです。
で、ググったけど最新すぎて英語でも情報が少なすぎたので、
- 新しい空のプロジェクトファイルを作成
- 定例の「Hello World」をxmlのLayoutファイルを読み込んで表示できるか確認
の手順でエラーが再現するか確認するとエラーは発生せず、「Hello World」が普通に表示された。
確認すると、workspace内に、「appcompat_v7」(android-support-v7-appcompatではない)というフォルダが自動で生成、インポートされていたので、それを利用したらエラーが解消w
再度言いますが、「android-support-v7-appcompat」ではなく、この「appcompat_v7」を利用する事で、全てのアプリでエラー解消。
あ、メモブログなので超適当です。要点だけ簡単に書いてるけど、同じエラー出た人にはすぐに分かると思いますw
また、appcompat_v7だけでなくgoogle-play-services_libでもエラーが出たけど、内容はアプリのメタデータに
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
をAndroidManifest.xmlに記述しないといけない的なエラーメッセージが出ました。
もちろん記述文章は今までと同じで、かつ、記述済みですよ。
で、このエラーに関しては、インポート時にworkspaceに直接「google-play-services_lib」をコピーするのではなく、リンクする事でエラーが解決。
えっと、Android Studioではエラー出ない?早くEclipseから乗り換えろって事ですか?
でも時間なくて結局まで移行作業進まず。
正確にはAndroid Studioの仕様をテストプロジェクト作って試し、ある程度仕様を実際に理解してから移行したいのでまだ出来てない感じです。
話変わるけど、このアプリの思い出だけど、2012年10月、上海へ初めて仕事で行く前に修正してうぷ&ブログにも書いてたんだよね。。
時間が経つのは本当に早いですなぁ・・。
まぁ時間無いので超速攻で適当にペイントソフトの作成時にはまった部分をメモ書きしましたが、参考になれば幸いです!