メニューの種類
コンテキスト メニューとポップアップ メニューの違いを概説することから始めましょう (ここから取得)。
PopupMenu は、Viewに固定されたモーダル メニューです。
コンテキスト メニュー [特にフローティング コンテキスト メニューについて話している] は、UI の特定の項目またはコンテキスト フレームに影響を与えるアクションを提供します。任意のビューにコンテキスト メニューを提供できますが、ほとんどの場合、ListView、GridView、またはユーザーが各項目に対して直接操作を実行できるその他のビュー コレクション内の項目に使用されます。
ガイダンスとして、ドキュメントでは用途を区別しています: - PopupMenu: "特定のコンテンツ (Gmail のメール ヘッダーなど)に関連するアクションにオーバーフロー スタイルのメニューを提供する..." - ContextualMenu: "選択したコンテンツに影響するアクションの場合... "
私はPopupMenuの視覚的な外観と相互作用を求めています。
私のセットアップ(および目標)
各項目の右側にボタンがある ListView があります。
--------------------
| Item 1 [ ]|
--------------------
--------------------
| Item ... [ ]|
--------------------
--------------------
| Item n [ ]|
--------------------
各 ListItemを保持しながらonItemClick
、ボタンを活用して をトリガーしたいと思いますPopupMenu
。
のアクションは にPopupMenu
リストされているmy_menu.xml
ため、メニューの各インスタンスの唯一の違いは、クリックされた項目です。
私が試したこと
この投稿に従って、 for each ボタンを追加するためにオーバーライドを試みましgetView()
た。結果は矛盾していました。すべてのクリックが登録されたわけではありません (おそらくリサイクルが原因です - 私はまだこの修正を試していません)。ListAdapter
OnClickListener
また、リスト項目が長押しされたときにのみトリガーされることを除いて、非常に簡単なコンテキスト メニューを追加しようとしました。
getView()
メソッドは進むべき道ですか、それとももっと簡単なものがありますか?
私のリストビューには、Play Music のプレイリストの各トラックと同様に、アイテムごとにミニ オーバーフロー ボタンがあります。オーバーフロー ボタンをクリックすると、各アイテムの PopupMenu が表示されます。長押しは何もしません。
私はそれが欲しいのですが、方法がわかりませんか?メニュー ページでは、個々のビューのポップアップ メニューを有効にする方法についてのみ詳しく説明しています。
registerForContextMenu(ListView lv)
ListView全体に適用できるのは私が見た唯一のものですが、それはリスト全体の長押しでのみ機能するようです。そのイベントをリスト項目の特定のビューのクリックにフックする方法はありますか (リスト項目の残りのリスト項目のクリックを維持しながら)?
onClickListener
ここで説明されているようにを設定しようとしましgetView()
たが、PopupMenu がぎこちなく感じられ、すべてのクリックが毎回登録されるわけではありません (常に一貫性がありませんでした)。
更新 - getView() を再度オーバーライドして
StacksCursorAdapter を作成するときに、フィールドとして格納されている StackViewFragment のインスタンスを渡します (これにより、クリック リスナーとしてビューに割り当てることができます)。
ViewHolder
のクラスですpublic final ImageView miniOverflow
StacksCursorAdapter (SimpleCursorAdapter を拡張):
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
}
holder.miniOverflow.setTag(R.id.tag_stack_position, position);
holder.miniOverflow.setOnClickListener(listener);
return row;
}
StackViewFragment (ListFragment を拡張し、View.OnClickListener を実装):
@Override
public void onClick(View v) {
Log.d(TAG, "mini overflow clicked");
Log.d(TAG, "position:::::" + v.getTag(R.id.tag_stack_position));
PopupMenu popup = new PopupMenu(getActivity(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_stackview_listitem, popup.getMenu());
popup.show();
}
stack_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- a single row item for a Stacks listview -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:descendantFocusability="blocksDescendants"
>
...
<other views>
...
<ImageView
android:id="@+id/moreoverflow_btn"
android:focusable="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:alpha="0.4"
android:scaleType="fitCenter"
android:src="@drawable/ic_menu_moreoverflow_black"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
このジャンクションでの問題は、(ボタン上で) 登録するためのクリックを取得するために、ときどき数回クリックする必要があることです。これはスクロールしないため、ビューのリサイクルとは関係ありません。
結論(正しいとマークされたeskimoapps.comによる解決策)
したがって、タッチ ターゲットが期待していた場所にないことを除いて、複数のクリックに問題はありませんでした。ミニ オーバーフローに使用していた画像アセットは右に重み付けされています (3 つの点が画像の右端近くにあるように)。タッチ ターゲット) は、半分の時間 (facepalm)を見逃していたことを意味します。
getView()
上で示したオーバーライドは問題なく機能しているようで、実際にgetView()
は、必要な場合にのみ OnClickListener を設定することでさらに変更できます (ただし、タグの更新は、新しく作成されたビューだけでなく、すべてのビューに対して行う必要があります)。 :
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
holder.miniOverflow.setOnClickListener(listener);
}
holder.miniOverflow.setTag(R.id.tag_stack_position, position);
return row;
}