Googleの新しいAPI、特にアクションバーを使用しようとしています。
ビルドがapi 10に設定されたときに、メニューボタンを押すと、素敵な外観のメニューオプションがあり、それぞれに画像とアイコンがありました。 API 14を使用する場合、何を試しても、常にテキストなしでアイコンがアクションバーに配置されます。私は考えられるすべてを試しました。 「テキスト付き」プロパティを指定し、テキストを1文字に変更しました(部屋の問題の場合)が、何もしませんでした。
これは、Android.developerの開発者ガイドでも前に見たことがありますが、それを表示する方法についての答えは見つかりません。
狭いアクションバーに単一のメニュー項目のテキストとアイコンを表示しないことは、Android開発者による意識的な決定だったと思われます。しかし、本当にしたい場合は、使用できます- Android:actionLayout menu.xmlファイルにあります。 Android ActionBarのドキュメント には、もう少し良い説明があります。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@+id/menu_foo"
Android:title="@string/menu_foo"
Android:icon="@drawable/ic_menu_foo"
Android:showAsAction="always"
Android:actionLayout="@layout/action_button_foo" />
</menu>
次に、action_button_foo.xml
レイアウト:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:paddingTop="14dp"
Android:paddingBottom="14dp"
Android:gravity="center"
Android:text="@string/menu_foo"
Android:drawableLeft="@drawable/ic_menu_foo"
Android:background="@drawable/bg_btn_action_bar"
Android:clickable="true" />
背景にセレクタを使用しますbg_btn_action_bar.xml
ので、タップすると色が変わります。
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:state_pressed="true"
Android:drawable="@drawable/bg_action_bar_pressed" />
<item
Android:drawable="@color/transparent" />
</selector>
次に、カスタムビューでクリックイベントを処理できるようにする必要があります。アクティビティでは、onOptionsItemSelected
のクリックを他のすべての非カスタムアイテムと一緒に処理できるように、これを実行します。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
final MenuItem item = menu.findItem(R.id.menu_foo);
item.getActionView().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onOptionsItemSelected(item);
}
});
return super.onCreateOptionsMenu(menu);
}
これは、4.0.4を実行しているNexus Sで確認したこととまったく同じです。私のアプリは、フラグメントとして実装されるいくつかのタブを持つアクションバーを使用します。私のさまざまなフラグメントは、タブが表示されている間にアクションバーに表示されるメニューオプションを調整します。
これは、Nexus Sとエミュレーター(HVGAとWVGA800の両方)で次のように一貫して実行されるため、ICSのバグのようです。
タブスピナーのその他の不具合に気付き、このICSの小さな角は少し乱雑/バギーです。アプリケーションに狭いディスプレイでアクションバーを分割するように指示した場合( Android:uiOptions="splitActionBarWhenNarrow"
をマニフェストに追加することにより、ICSは、上部にまだ十分なスペースがあるにもかかわらず、それらのアイテムを常に下部のバーにプッシュします。テキストは表示されず、アイコンのみが表示されます。
4.0.4を実行しているXoomでは、十分なスペースがあるため、タブとアクションアイテムは常に期待どおりに表示されます。
回避策:ポートレートモードでアクションバーにテキストが本当に必要な場合は、アイコンを放棄する必要があります。メニュー項目からアイコンを削除すると、テキストが表示されます。しかし、これは私たちが望んでいることとはまったく異なります。
バグレポートをここに投稿しました: https://code.google.com/p/Android/issues/detail?id=3018 。
「withText」プロパティは、ほとんどのタブレットで動作しますただし、小さなデバイスでアイコンとテキストを取得する簡単な方法は、アイコンの横にテキストを1つの画像(PNGファイル)として追加することです。これにより、テキストとアイコンの両方が1つのアイコンとして表示され、全体が表示されます。
WithTextプロパティを使用して、タブレットの元のアイコンを使用できます。
「menu-w600dp」というタイトルのresディレクトリに追加のメニューフォルダーを作成する必要があります。
このフォルダー内のoptionmenu.xmlは、600dpを超える画面幅(アイコンとテキストを問題なく表示するもの)にのみ適用されます。
Honeycombのオプションバーをアクションバーに表示するには、次のようにしました。
アクティビティで、この関数をオーバーライドします。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actionbar_universe, menu);
return true;
}
r.menu.actionbar_universeは、メニュー項目を次のように定義します。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@+id/crossholdings" Android:showAsAction="always|withText"
Android:title="Cross Holdings" Android:icon="@drawable/actionbar_cross"/>
</menu>
ShowAsAction = "always | withText"に注意し、Android:titleを指定します。
それがあり、機能しない場合は、ここにメニューリソースをコピーして貼り付けてください。
編集:これは間違った質問に答えますが、それは元のテキストです。
このコードを使用してアクションバーのタイトルを設定し、会社のロゴで赤くペイントします。 3.0ではうまく機能します。
public ActionBar setActionBarStyle(String title) {
ActionBar actionBar = setActionBarStyle();
actionBar.setTitle(title);
return actionBar;
}
public ActionBar setActionBarStyle() {
ActionBar actionBar = getActionBar();
ShapeDrawable actionBackground = new ShapeDrawable();
actionBackground.getPaint().setColor(Color.RED);
actionBackground.setBounds(0, 0, 5, 5);
actionBar.setBackgroundDrawable(actionBackground);
actionBar.setDisplayUseLogoEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
return actionBar;
}
私は多くのオプションを試しましたが、単純な「トリック」を思いつきましたwithout奇妙なコード行、without画像。また、カスタムactionLayoutを使用した最初のソリューションは、APIレベル10の互換性では動作しませんでした。
小さなアクションバーにテキストとアイコンを表示したい場合、スペースがあることを知っていますか?したがって、2つのメニュー項目を使用できます。
必要に応じて「ifRoom」のテキストアクションを選択して、スペースが必要な場合にテキストが消えるようにします。ただし、アクションバー上でさらにスペースが必要になりますが、私にとっては良い妥協でした。私は次のコードになります:
<item
Android:id="@+id/menu_save"
Android:icon="@drawable/save"
pelmel:showAsAction="always">
</item>
<item
Android:id="@+id/menu_save_text"
Android:title="@string/profileSave"
pelmel:showAsAction="ifRoom">
</item>
([〜#〜] edit [〜#〜]「pelmel」はアプリ名ですEND EDIT)
そして、選択ハンドラは両方のIDをキャッチするだけです:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_save:
case R.id.menu_save_text:
// Your code here
return true;
}
}
この問題を修正するには、「アプリでサポートライブラリを使用している場合」 XMLでアクションを指定 の下のセクションを使用します。
... Android 2.1以降のバージョンでの互換性のため、showAsAction属性は
Android:
名前空間。代わりに、この属性はサポートライブラリによって提供されます。独自のXML名前空間を定義し、その名前空間を属性プレフィックスとして使用する必要があります。 (カスタムXML名前空間はアプリ名に基づいている必要がありますが、任意の名前にすることができ、宣言したファイルのスコープ内でのみアクセスできます。)例:
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:yourapp="http://schemas.Android.com/apk/res-auto" >
<!-- Search, should appear as action button -->
<item Android:id="@+id/action_search"
Android:icon="@drawable/ic_action_search"
Android:title="@string/action_search"
yourapp:showAsAction="ifRoom" />
...
</menu>
これらの他のもののどれもあなたのために働かない場合、これはかもしれない。
Dgmltnにほぼ基づいた別のオプションがあります。利点:
この例では、ActionBarSherlockを使用していると想定しています。最初に、必要なビューレイアウトを作成します。これはActionBarSherlockに基づいています。変更したのは、画像/ビューを入れ替えて、共有マージン/パディングを0に減らしてそれらを近づけ、すべてのABSスタイルを解決することだけでした。
<com.example.views.ActionMenuTextItemView xmlns:Android="http://schemas.Android.com/apk/res/Android"
style="@Android:style/Widget.Holo.ActionButton"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:addStatesFromChildren="true"
Android:focusable="true"
Android:gravity="center"
Android:clickable="true"
Android:paddingLeft="4dip"
Android:paddingRight="4dip" >
<com.actionbarsherlock.internal.widget.CapitalizingButton
Android:id="@+id/abs__textButton"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:background="@null"
Android:ellipsize="none"
Android:focusable="false"
Android:minHeight="48dip"
Android:minWidth="48dip"
Android:paddingBottom="4dip"
Android:paddingLeft="4dip"
Android:paddingRight="0dip"
Android:paddingTop="4dip"
Android:singleLine="true"
Android:textAppearance="@Android:style/TextAppearance.Holo.Widget.ActionBar.Menu"
Android:textColor="#fff3f3f3" />
<ImageButton
Android:id="@+id/abs__imageButton"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:layout_marginBottom="4dip"
Android:layout_marginLeft="0dip"
Android:layout_marginRight="4dip"
Android:layout_marginTop="4dip"
Android:adjustViewBounds="true"
Android:background="@null"
Android:focusable="false"
Android:scaleType="fitCenter"
Android:visibility="gone" />
</com.example.views.ActionMenuTextItemView>
次に、対応するView
クラスを作成します。内部のものの使用が心配な場合は、CapitalizingButton
をコピーすることをお勧めします。また、最小幅のものを修正したこともありません。それは本当に重要だとは思わないでください。
package com.example.views;
import Android.annotation.SuppressLint;
import Android.content.Context;
import Android.graphics.drawable.Drawable;
import Android.os.Build;
import Android.text.TextUtils;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.view.accessibility.AccessibilityEvent;
import Android.widget.ImageButton;
import Android.widget.LinearLayout;
import com.actionbarsherlock.R;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.internal.widget.CapitalizingButton;
import com.actionbarsherlock.view.MenuItem;
@SuppressLint({ "NewApi" })
public class ActionMenuTextItemView extends LinearLayout implements OnClickListener
{
private ImageButton mImageButton;
private CapitalizingButton mTextButton;
private Object mTarget;
private MenuItem mItem;
// Set up all the data. Object must be a sherlock activity or fragment with an onMenuItemSelected().
public void initialise(MenuItem item, Object target)
{
mItem = item;
mTarget = target;
setIcon(mItem.getIcon());
setTitle(mItem.getTitle());
}
public ActionMenuTextItemView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ActionMenuTextItemView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public void onFinishInflate()
{
super.onFinishInflate();
mImageButton = (ImageButton) findViewById(R.id.abs__imageButton);
mTextButton = (CapitalizingButton) findViewById(R.id.abs__textButton);
mImageButton.setOnClickListener(this);
mTextButton.setOnClickListener(this);
setOnClickListener(this);
}
@Override
public void setEnabled(boolean enabled)
{
super.setEnabled(enabled);
mImageButton.setEnabled(enabled);
mTextButton.setEnabled(enabled);
}
public void setIcon(Drawable icon)
{
mImageButton.setImageDrawable(icon);
if (icon != null)
mImageButton.setVisibility(VISIBLE);
else
mImageButton.setVisibility(GONE);
}
public void setTitle(CharSequence title)
{
mTextButton.setTextCompat(title);
setContentDescription(title);
}
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event)
{
onPopulateAccessibilityEvent(event);
return true;
}
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
super.onPopulateAccessibilityEvent(event);
final CharSequence cdesc = getContentDescription();
if (!TextUtils.isEmpty(cdesc))
event.getText().add(cdesc);
}
@Override
public boolean dispatchHoverEvent(MotionEvent event)
{
// Don't allow children to hover; we want this to be treated as a single component.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
return onHoverEvent(event);
return false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int minWidth = 0;
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int specSize = MeasureSpec.getSize(widthMeasureSpec);
final int oldMeasuredWidth = getMeasuredWidth();
final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, minWidth) : minWidth;
if (widthMode != MeasureSpec.EXACTLY && minWidth > 0 && oldMeasuredWidth < targetWidth)
{
// Remeasure at exactly the minimum width.
super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
}
@Override
public void onClick(View v)
{
if (mTarget == null)
return;
else if (mTarget instanceof SherlockActivity)
((SherlockActivity)mTarget).onOptionsItemSelected(mItem);
else if (mTarget instanceof SherlockFragmentActivity)
((SherlockFragmentActivity)mTarget).onOptionsItemSelected(mItem);
else if (mTarget instanceof SherlockListActivity)
((SherlockListActivity)mTarget).onOptionsItemSelected(mItem);
else if (mTarget instanceof SherlockListFragment)
((SherlockListFragment)mTarget).onOptionsItemSelected(mItem);
else if (mTarget instanceof SherlockFragment)
((SherlockFragment)mTarget).onOptionsItemSelected(mItem);
else
throw new IllegalArgumentException("Target must be a sherlock activity or fragment.");
}
}
これで使用準備が整いました。テキストが必要なメニュー項目で、dgmltnが言ったことと同じことを行います。
<item
Android:id="@+id/menu_foo"
Android:icon="@drawable/..."
Android:showAsAction="always|withText" // Doesn't do anything really.
Android:title="Sell"
Android:titleCondensed="Sell"
Android:actionLayout="@layout/view_action_menu_text_item"/> // Or whatever you called it.
最後に、このコードをアクティビティ/フラグメントに追加します。
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
getSupportMenuInflater().inflate(R.menu.activity_main, menu);
// The magic lines.
MenuItem it = menu.findItem(R.id.menu_foo);
((ActionMenuTextItemView)it.getActionView()).initialise(it, this);
以上です!