リストビューにレコードのリストがあり、ユーザーがドラッグアンドドロップメソッドを使用して再ソートできるようにしたい。これは他のアプリに実装されているのを見てきましたが、チュートリアルは見つかりませんでした。それは他の人にも必要なものでなければなりません。これを行うためのコードを誰かに教えてもらえますか?
リストビューにレコードのリストがあり、ユーザーがドラッグアンドドロップメソッドを使用して再ソートできるようにしたい。これは他のアプリに実装されているのを見てきましたが、チュートリアルは見つかりませんでした。それは他の人にも必要なものでなければなりません。これを行うためのコードを誰かに教えてもらえますか?
回答:
私はこれにしばらく取り組んできました。正しく理解するのは難しいですが、そうは言えませんが、今のところ満足しています。私のコードといくつかのデモは、
その使用法はTouchInterceptor(コードのベース)とよく似ていますが、実装に大幅な変更が加えられています。
DragSortListViewは、アイテムのドラッグおよびシャッフル中に、スムーズで予測可能なスクロールを行います。アイテムのシャッフルは、ドラッグ/フローティングアイテムの位置とはるかに一貫しています。高さの異なるリスト項目がサポートされています。ドラッグスクロールはカスタマイズ可能です(私は長いリストをすばやくドラッグスクロールすることを示しています---アプリケーションが思い浮かぶわけではありません)。ヘッダー/フッターが尊重されます。等。??見てください。
これでRecyclerView
、ItemTouchHelperを使用して簡単に実装できます。onMove
からのメソッドをオーバーライドするだけItemTouchHelper.Callback
です:
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
これに関するかなり良いチュートリアルは、medium.comにあります。RecyclerViewでドラッグアンドスワイプします。
これについてグーグルする人のためにこの答えを追加しています。
最近、これを行う方法を説明するDevBytes(ListViewセルのドラッグと並べ替え)の エピソードがありました
あなたはそれをここで見つけることができ、サンプルコードもここで利用可能です。
このコードが基本的に行うことは、セルのドラッグとスワッピングをサポートdynamic listview
するの拡張によってを作成することlistview
です。DynamicListView
基本の代わりにを使用できるようにするため に、ListView
ドラッグアンドドロップでListViewを実装しました。
DragListView libは、高度なアニメーションなどのカスタムアニメーションの非常に優れたサポートにより、これを本当に適切に実行します。また、定期的に維持および更新されます。
使い方は次のとおりです。
1:まずlibをgradleに追加します
dependencies {
compile 'com.github.woxthebox:draglistview:1.2.1'
}
2:XMLからリストを追加する
<com.woxthebox.draglistview.DragListView
android:id="@+id/draglistview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
3:ドラッグリスナーを設定する
mDragListView.setDragListListener(new DragListView.DragListListener() {
@Override
public void onItemDragStarted(int position) {
}
@Override
public void onItemDragEnded(int fromPosition, int toPosition) {
}
});
4:DragItemAdapterからオーバーライドされたアダプターを作成する
public class ItemAdapter extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder>
public ItemAdapter(ArrayList<Pair<Long, String>> list, int layoutId, int grabHandleId, boolean dragOnLongPress) {
super(dragOnLongPress);
mLayoutId = layoutId;
mGrabHandleId = grabHandleId;
setHasStableIds(true);
setItemList(list);
}
5:DragItemAdapter.ViewHolderから拡張するビューホルダーを実装する
public class ViewHolder extends DragItemAdapter.ViewHolder {
public TextView mText;
public ViewHolder(final View itemView) {
super(itemView, mGrabHandleId);
mText = (TextView) itemView.findViewById(R.id.text);
}
@Override
public void onItemClicked(View view) {
}
@Override
public boolean onItemLongClicked(View view) {
return true;
}
}
私が見つかりました。DragSortListViewは、それが簡単にされている可能性がで始めるが、うまくいきました。以下は、インメモリリストを使用したAndroid Studioでの使用に関する簡単なチュートリアルです。
これをbuild.gradle
アプリの依存関係に追加します。
compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
に作成または追加して、ドラッグハンドルIDのリソースを作成しますvalues/ids.xml
。
<resources>
... possibly other resources ...
<item type="id" name="drag_handle" />
</resources>
お気に入りのドラッグハンドルイメージを含むリストアイテムのレイアウトを作成し、そのIDをステップ2で作成したIDに割り当てます(例:)drag_handle
。
次のようなDragSortListViewレイアウトを作成します。
<com.mobeta.android.dslv.DragSortListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dslv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
dslv:drag_handle_id="@id/drag_handle"
dslv:float_background_color="@android:color/background_light"/>
リストアイテムビューをレンダリングArrayAdapter
するgetView
オーバーライドで派生物を設定します。
final ArrayAdapter<MyItem> itemAdapter = new ArrayAdapter<MyItem>(this, R.layout.my_item, R.id.my_item_name, items) { // The third parameter works around ugly Android legacy. http://stackoverflow.com/a/18529511/145173
@Override public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
MyItem item = getItem(position);
((TextView) view.findViewById(R.id.my_item_name)).setText(item.getName());
// ... Fill in other views ...
return view;
}
};
dragSortListView.setAdapter(itemAdapter);
ドロップされるときに項目を再配置するドロップリスナーを設定します。
dragSortListView.setDropListener(new DragSortListView.DropListener() {
@Override public void drop(int from, int to) {
MyItem movedItem = items.get(from);
items.remove(from);
if (from > to) --from;
items.add(to, movedItem);
itemAdapter.notifyDataSetChanged();
}
});
私は最近、外部ソートを必要とせずに、ドラッグソートの実用的な実装を提供するこの素晴らしいGistに出会いましたListView
。
基本的には、をArrayAdapter
含むアクティビティの内部クラスとして拡張するカスタムアダプタの作成で構成されますListView
。このアダプタonTouchListener
では、ドラッグの開始を知らせるリストアイテムにを設定します。
その要点では、リスナーをリストアイテムのレイアウトの特定の部分(アイテムの「ハンドル」)に設定しているため、誤ってリストの一部を押して移動することはありません。個人的に、私はonLongClickListener
代わりに行くことを好みましたが、それはあなた次第です。ここでその部分の抜粋:
public class MyArrayAdapter extends ArrayAdapter<String> {
private ArrayList<String> mStrings = new ArrayList<String>();
private LayoutInflater mInflater;
private int mLayout;
//constructor, clear, remove, add, insert...
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
//inflate, etc...
final String string = mStrings.get(position);
holder.title.setText(string);
// Here the listener is set specifically to the handle of the layout
holder.handle.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
startDrag(string);
return true;
}
return false;
}
});
// change color on dragging item and other things...
return view;
}
}
これにはへのの追加も含まonTouchListener
れますListView
。これは、アイテムがドラッグされているかどうかを確認し、スワッピングと無効化を処理し、ドラッグ状態を停止します。その部分の抜粋:
mListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!mSortable) { return false; }
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
// get positions
int position = mListView.pointToPosition((int) event.getX(),
(int) event.getY());
if (position < 0) {
break;
}
// check if it's time to swap
if (position != mPosition) {
mPosition = position;
mAdapter.remove(mDragString);
mAdapter.insert(mDragString, mPosition);
}
return true;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE: {
//stop drag state
stopDrag();
return true;
}
}
return false;
}
});
最後に、ドラッグプロセスの有効化と無効化を処理するstopDrag
およびstartDrag
メソッドの外観を次に示します。
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}