リストにボタンがあるListactivityでonListItemClickを起動する方法は?


89

カスタムListAdapterを使用してリスト内のビューを生成する単純なListActivityがあります。通常、ListAdapterはビューをTextViewで埋めるだけですが、今度はそこにもボタンを配置したいと思います。

ただし、フォーカス可能なビューをリストアイテムに配置すると、リストアイテムがクリックされたときにListActivityでonListItemClick()が呼び出されないことが私の理解と経験です。ボタンは引き続きリストアイテム内で正常に機能しますが、ボタン以外のものが押されたときに、onListItemClickがトリガーされるようにします。

どうすればこれを機能させることができますか?


5
子孫のフォーカス機能を備えたソリューションは本当に役に立ちます。回答として追加して受け入れる必要があります。
Maksym Gontar

@Max私がそうしない理由は、それが本当に悪い習慣、回避策だからです。私がこれまでに永続的な健康的な解決策を見つけた場合、私はその答えを出します(私がこの質問を1年前に書いたことを覚えている場合:))
CodeFusionMobile

私もあなたが持っている回避策を見たいです。子孫のフォーカスを設定しようとしていますが、ボタンを操作できません。また、GridView(ImageViewを含む)をリスト行に配置しようとしていますが、これにも同様の問題があります。
MrPurpleStreak 2010

私が与えた私見の答えは、ランプスとプラビーンが提案した問題よりもはるかにエレガントな解決策です。Psここでは忘れられた質問を復活させようとはしていませんが、まだ回答を受け入れていません; D
Ewoks

@CodeFusionMobile Ewoksの回答を受け入れてもらえますか?ListView要素のオンクリックアニメーションが無効になるため、投票数が最も多い回答には問題があります(青色に変わります)。他の開発者がトップアンサーを試して、それが欠陥であることを発見し、それからEwoksに行くのに費やす時間を節約できます。
1

回答:


99

以前のコメントソリューションで書いたように、ImageButtonでsetFocusable(false)を実行します。

リスト要素のandroid:descendantFocusability="blocksDescendants" ルートレイアウトに追加しようとするさらにエレガントなソリューションがあります。これにより、onListItemのクリックが可能になり、個別にButtonまたはImageButtonのクリックを処理できます。

それが役に立てば幸い ;)

乾杯


3
android:descendantFocusability="blocksDescendants"完璧だった。
マシューミッチェル

1
あなた、私の友人は私の個人的なヒーローです。あなたが一番投票した人になるはずです!これはほとんどすべてのケースではるかに優れています!
OschtärEi

これは受け入れられる答えになるはずです。それは私には完璧に働きました。リストアイテムのすべてのビューをフォーカス不可にする必要があるようです。これは、それぞれを個別に設定することなくそれを実行します。
2013年

1
これは私にはうまくいかないようです。ルートレイアウトとは、行のレイアウトですか、それともリストビューが定義されている場所ですか?とにかく、私はすべての可能な組み合わせを試してみました..機能しません:(
GreenBee

「リスト要素のルートレイアウト」私が書いたように...それでは、あなたがリストとレイアウトから成るを持っているとしましょう、いくつかのボタンを持っている(リスト要素のそれらのルートレイアウトを呼び出す)、のImageButton、TextVeiw ...
イーウォック

59

ここでお手伝いできればと思います。listViewアイテムのカスタムレイアウトがあり、このレイアウトはボタンとTextView、ImageViewなどのその他のビューで構成されていると思います。ここで、ボタンをクリックしたときに別のイベントを発生させ、他のすべてのイベントをクリックしたときに別のイベントを発生させる必要があります。

ListActivityのonListItemClick()を使用せずにそれを実現できます。
これはあなたがしなければならないことです:

カスタムレイアウトを使用しているため、おそらくカスタムアダプターのgetView()メソッドをオーバーライドしています。秘訣は、ボタンに異なるリスナーを設定し、ビュー全体(行)に異なるリスナーを設定することです。例を見てみましょう:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

OnItemClickListenerクラスは次のように宣言できます。

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

もちろん、おそらくいくつかのパラメータをOnItemClickListenerコンストラクタに追加します。
そして、重要なことの1つ-上に示したgetViewの実装はかなり醜く、通常はViewHolderパターンを使用してfindViewById呼び出しを回避する必要があります。
私のcustom_row.xmlファイルは、ID "button"のボタン、ID "text"のTextView、ID "image"のImageViewを持つRelativeLayoutです。
よろしく!


9
私の解決策は別の方向に進んでしまいました。リスト行レイアウトの子孫のFocusabilityプロパティを子孫をブロックするように設定することで問題を解決しましたが、突然機能しました。今度は、simpleCursorAdapterにカスタムビューバインダーをアタッチして、イベントの設定やボタンに関連するその他の豪華なことを行います。
CodeFusionMobile 2010年

3
このソリューションを使用しました。ただし、警告:onClickハンドラーによってリストの内容が変更された場合、getViewが呼び出され、かつウィジェットがステートフル(ToggleButtonやCheckBoxなど)であり、かつgetViewがその状態を設定する場合、setOnClickListener (null)onViewで状態を変更する前に、ループ効果の発生を回避します。
Pierre-Luc Paour 2011年

3
私の解決策はどうですか?我々はそれを必要とする時はいつでも私は、よりエレガントでかつ容易に適用することができた印象を持っている...
イーウォック

最初のコメントは回答として受け入れる必要があるので、私のような人はそれを見つけるのに何時間も必要ないでしょう
keybee

ありがとう!これは役に立ちました。他のスレッドで説明されているfocus:blockDescendantsアプローチのよりローカライズされた代替手段として私はそれを気に入っています。
Yoav Shapira

18

カスタムリストビューにフォーカス可能な要素が含まれている場合、onListItemClickは機能しません(これは予想される動作です)。カスタムビューからフォーカスを削除するだけで、トリックが実行されます。

例えば:

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
               
    }
}

3
私はあなたのソリューションが好きです:行ごとに「クリック可能な」ウィジェットが1つしかない場合、それらのフォーカスを拒否することはエレガントなソリューションです。これは、行の任意の場所のタップが一致することを意味しますが、ウィジェットがラジオまたはチェックボックスの場合に便利な動作です。同じことは、android:focusable = "false"とandroid:focusableInTouchMode = "false"を使用してXMLで実現できます。
Pierre-Luc Paour、2011年

1
可視性を変更した場合、xmlの方法は機能しないようです。そのため、 "View"をvisibleに設定した後、コードを通じて実行する必要があります
max4ever

13

同じ問題があります:OnListItemClickが発生しません![解決済み]
これ
は、ListActivityを拡張するクラスで発生し、TextBoxとListViewを内容とするListActivityのレイアウトがLinearLayoutにネストされます。
、別のレイアウトが行用です(CheckraとTextBoxがLineraLayoutにネストされています)。

それはコードです:

res / layout / configpage.xml(メインはListActivity)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" > 
    <TextView  
        android:id="@+id/selection"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="pippo" /> 
    <ListView  
        android:id="@android:id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:drawSelectorOnTop="false"  
        android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"> 
  <CheckBox  
      android:id="@+id/img"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 

  <TextView  
      android:id="@+id/testo"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ ConfigPage.java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

これは、row.xmlに追加したときに機能し始めます

  • android:focusable="false"
  • android:focusableInTouchMode="false"

私はEclipse 3.5.2
Android SDK 10.0.1 を使用しています
min SDKバージョンます:3

私はこれが役立つことを願っています
...そして私の英語:(


@fellonsはその理由を知りませんが、私にはうまくいきませんでした。onListItemClickが呼び出されていません。
likejudo 2014

プロパティコードandroid:focusable = "false"およびandroid:focusableInTouchMode = "false"コードを追加しましたか?
rfellons 2014

2

android:focusable="false"ボタンの属性の1つとして追加するだけです


1

ToggleButtonでも同じ問題が発生しました。壁に頭をぶつけた半日後、ようやく解決しました。「android:focusable」を使用して、フォーカス可能なビューを非フォーカスにするのと同じくらい簡単です。また、リストの行のフォーカス可能性とクリック可能性(私は単語を作成しただけです)をいじることは避け、デフォルト値のままにしてください。

もちろん、リスト行のフォーカス可能なビューはフォーカスできないため、キーボードを使用しているユーザーは問題を抱えている可能性があります。問題になることはほとんどありませんが、100%完璧なアプリを作成したい場合に備えて、onItemSelectedイベントを使用して、選択した行の要素をフォーカス可能にし、以前に選択した行の要素をフォーカス不可能にすることができます。


私はこのアプローチを使用しました。個々のアイテムに集中できないという問題を回避できる場合は、これが最も簡単な方法です。これにより、リストアイテムの状態のドローアブルが本来あるべき状態で維持されますが、他の回避策の一部ではそうではありません。
ジョナサンS.

1
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});

-1

アイテム内に値を保持するオブジェクトをインスタンス化するgetListAdapter()。getItem(position)を使用しました

MyPojo myPojo = getListAdapter().getItem(position);

次に、myPojoのgetterメソッドを使用して、アイテム内の適切な値を呼び出します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.