Android-リストビューの遅延クリック
-
26-10-2019 - |
質問
アプリには次の構造があります。
fragmentActivityで ViewPager
管理された複数のフラグメントを保持します FragmentStatePagerAdapter
Android 2.1を使用した互換性パックを使用します
各フラグメントには含まれています ListView
. 。の各要素 ListView
があります LinearLayout
2つで TextViews
そしてa Button
. 。 LinearLayout
そしてボタンがあります onClickListeners
(分ける)。をクリックします LinearLayout
別のものを開始します Activity
. 。クリック動作が非常に一貫性がないことに気付きました。時にはアクションがすぐに実行されることもありますが、非常に頻繁に遅延が発生し、何回タップしても無視されます。タップできるため、それはさらに奇妙になり、アクションはリストのスクロールを開始したときにのみ実行されます。さまざまな組み合わせを試しました setFocusable(false)
と setSelectable(true)
しかし、違いはないようです。何か案は?詳細を提供させていただきます。
解決 3
誰かが私がこれをどのように解決したのか疑問に思った場合。基本的に、レイアウトを簡素化する必要がありました。複雑なネストされた構造がある場合、イベントはバブルに時間がかかりすぎる場合があり、同時にイベントでスクロールリストを開始すると、間違ったアクションがトリガーされる可能性があります。できるだけlerativelayoutに切り替えることでレイアウトをトリミングしましたが、それは大いに役立つように思えました
他のヒント
同様の問題があり、デバッグして解決するのに2日かかりました。すべてのリストアイテムのLinearLayoutでいくつかのテキストビューを作成するリストアダプターがあります。各TextViewには、各アイテムのクリックを処理する必要があるため、独自のOnClickListenerがあります。
実装を変更したときに、onclickListenerが正しく動作を停止したビューを再利用するようにしました。 4.4.2では、ほとんどのクリックが機能しましたが、リストにスクロールするまで反応がなかった場合があります。 2.3では、最初のクリックが機能せず、その後、すべてのクリックがバーストで処理されます。
私の特別なケースでは、リソースを膨らませるのではなく、Javaコードですべてのビューを作成しました。そして、重要なポイントは、ビューが再利用されたときでさえ、LinearLayoutのレイアウトパラムを設定したことです(これはより安全であるように思われ、再利用ビューに正しいレイアウトパラメーターがあると仮定して)。レイアウトパラムを設定しないときは、すべてを再利用するときはすべて正常に機能します!これが重要なコードです:
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout tapeLine = null;
if (convertView != null && convertView instanceof LinearLayout && ((LinearLayout)convertView).getChildCount() == 4) tapeLine = (LinearLayout) convertView; // Reuse view
else tapeLine = new LinearLayout(activity);
if (convertView == null) { // Don't set LayoutParams when reusing view
ViewGroup.LayoutParams tapeLineLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tapeLine.setLayoutParams(tapeLineLayoutParams);
}
ScrollingTape scrollingTape = calculatorHolder.getCalculator().getScrollingTape();
int tapeWidthPx = parent.getWidth();
TapeLineTextSizeInfo tapeLineTextSizeInfo = calculatorHolder.getTapeLineTextSizeHelper().createTapeLineTextSizeInfo(tapeWidthPx);
ScrollingTapeLine line = scrollingTape.getLine(position);
tapeLine.setOrientation(LinearLayout.HORIZONTAL);
int tapeBackgroundColor = getBackgroundColor(line);
tapeLine.setBackgroundColor(tapeBackgroundColor);
addColumnViews(tapeLine, line, tapeLineTextSizeInfo);
tapeLine.setTag(R.id.scrollingtapeadapter_viewtag_position, position);
tapeLine.setOnLongClickListener(longClickListener);
tapeLine.setOnClickListener(remainClickListener);
return tapeLine;
}
リストビューのこの奇妙な動作の背景は何ですか? Androidソースで少しデバッグと調査を行いました。 Androidがビューを更新すると、オンメジャーとオンレイアウトの2つの重要な手順があります。 ListAdapterのgetViewメソッドは、ビューを描くためだけでなく、測定中にも早い段階で呼ばれます。この後のケースでは、ビューが作成されますが、クリックイベントを処理するためにイベントチェーンにまだ登録されていません。
オンメジャー用に作成されたビューが後で再利用され、画面に積極的に描かれるように再利用される場合、クリックイベントを処理するためにAndroidシステムから登録する必要があります。この特別なケースのために、Android Develepersは何かをしましたが、これは汚いハックと見なすことができます。 LayoutParamsの特別なフラグは、イベントの変更でビューを登録する必要があることを決定するために使用されます。
私の問題:ビューが再利用されたときにもレイアウトパラムをリセットすることにより、このフラグは常にリセットされました。したがって、Androidシステムはビューを登録せず、イベントは実現しません。
要約すると、ListAdapterのGetViewでビューを再使用する場合、Androidシステムの内部情報を保持しているため、LayoutParamsを上書きしないでください。
私は同じ問題に遭遇しましたが、私の場合、解決策はビューへの参照を維持することではなく、ListViewのビューキャッシングの問題を引き起こしました。適切に実装した後 getView()
ConverViewを使用した方法では、失われた /予期しないクリックコールを使用したすべての奇妙な動作がなくなりました。
私のために働いていたのは、Anを割り当てることでした OnItemClickListener
に ListView
終えた setOnItemClickListener
, 、ではなく OnClickListener
個々のリスト項目に。明らかに、ボタンにはまだ独自のボタンが必要です OnClickListener
, 、しかし、私はそのシナリオをテストしていません。
これが誰かに役立つかどうかはわかりませんが、代わりにTableLayoutで同様の問題がありました。上記のソリューションは私の問題を修正しませんでした。
私にとって問題は次のとおりです。android:animateLayoutChanges="true"
これを削除すると、TableLayout行内のボタンクリックが適切に動作しました。その後、上記のプロパティに依存するのではなく、手動で意見をアニメーション化する必要がありました。
イベントスレッドでいくつかのブロッキングプロセス(Webサービスの呼び出しやファイルの開くなど)を実行しているようで、イベントスレッドがブロックされているようです。この場合、ブロックコードをイベントスレッドよりも別のスレッドに処理してください。