隠しリソースを使う
アクションバーに「リフレッシュ」ボタンをつけようとして、次のようなメニューリソースを書いた。
<item android:id="@+id/action_refresh" android:icon="@android:drawable/ic_menu_refresh" android:showAsAction="always" android:title="@string/action_refresh"/>
すると "error: Error: Resource is not public. (at 'icon' with value '@android:drawable/ic_menu_refresh')." というエラーがでてリソースをコンパイルできない。
SDK の res/drawable-hdpi/ などの下に画像はあるけれど、どうやら OS のバージョンなどによって存在したりしなかったり、というリソースは private 指定されているのだとか。
ということで先のリソース定義から android:icon="..." 行を削除して、オプションメニューを生成時に動的にアイコンを設定するように変更。
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); final String idString = "@*android:drawable/ic_menu_refresh"; final int id = getResources().getIdentifier(idString, null, null); menu.findItem(R.id.action_refresh).setIcon(id); return true; }
非公開のリソースは @android でなく @*android とすれば参照できるのだとか。
Resources#getIdentifier() で非公開リソースの ID を探し、これを MenuItem#setIcon() で設定している。
非公開リソースが見つからなかった場合は文字列 @string/action_refresh が表示される。
というのは Resources#getIdentifier() は見つからなければ 0 を返す。 MenuItem#setIcon() に 0 を渡すとアイコン設定を削除する(ドキュメントには書かれていないので、動かして確かめた限りだけれど)。よって指定した文字列が表示される。
昔の SDK ではリソース定義に @*android を指定できたのかもしれないけれど、 SDK 22.0.5 では "Illegal resource reference: @*android resources are private and not always present" とエラーがでてコンパイルできない。よってコードで対応するしかなさそう。