안드로이드 목록보기 드래그 앤 드롭 정렬


132

드래그 앤 드롭 방법을 사용하여 사용자가 다시 정렬 할 수 있도록 목록보기에 레코드 목록이 있습니다. 다른 앱에서 구현 된 것을 보았지만 튜토리얼을 찾지 못했습니다. 다른 사람들도 필요로하는 것이어야합니다. 누구 든지이 작업을 수행하는 코드를 알려줄 수 있습니까?


1
정렬 가능한 목록보기를 만드는 데 도움이되는이 자습서를 찾았습니다 . 아직 테스트하지는 않았지만 비디오는 유망 해 보입니다.
— Alex

@Arkde 농담, 그들은 몇 년 후에도이 질문에 대한 대답을 수락하지 않았습니다.
— ArtOfWarfare 17:37에

@ArtOfWarfare 나는 불행한 일이 아스카에게 일어날 수 있다고 생각해야한다고 생각합니다. 추가 활동을 허용하지 않습니다.
— heycosmo

1
@heycosmo 그것은 가능합니다 ... 그들의 SO 프로필에 따르면, miannelle은 질문을한지 불과 한 달 만에 마지막으로 방문했습니다. 또한 DSLV에 대한 훌륭한 작업 ... 더블 탭과 같은 항목으로 항목을 복제하고 드래그 할 때 항목의 그림자를 변경하도록 항목을 약간 수정했습니다 (항목마다 행 번호가 있으므로 행 번호 업데이트가 드래그 될 때 업데이트 될 수 있도록 만들었습니다.) 그들은 클래스의 다른 모든 것보다 훨씬 덜 해킹되어 GitHub에 변경 사항을 제출하지 않은 이유입니다.
— ArtOfWarfare 4

github.com/bauerca/drag-sort-listview 이것을 사용하고 있으며 ListView의 ROW onLongClick을 드래그 할 수 있습니까?
— Achin

답변:


85

나는 지금 얼마 동안이 일을 해왔다. 이해하기 힘들고, 내가 주장한다고 주장하지는 않지만 지금까지는 만족합니다. 내 코드와 몇 가지 데모는

코드의 기반이되는 TouchInterceptor와 매우 유사하지만 구현이 크게 변경되었습니다.

DragSortListView에는 항목을 드래그하고 섞는 동안 부드럽고 예측 가능한 스크롤이 있습니다. 항목 셔플은 드래그 / 플로팅 항목의 위치와 훨씬 더 일관됩니다. 이기종 높이 목록 항목이 지원됩니다. 드래그 스크롤은 사용자 정의가 가능합니다 (응용 프로그램이 아니라 긴 목록을 통해 빠른 드래그 스크롤을 보여줍니다). 머리글 / 바닥 글이 존중됩니다. 기타.?? 구경하다.


3
귀하의 솔루션은 매력처럼 작동합니다. 다른 사람들보다 훨씬 낫습니다. 소스 코드의 라이센스는 무엇입니까? 아파치 2.0?
— 다리우스 바친 스키

1
@heycosmo 데모에서 제공된 뷰를 사용하여 앱에서 레이아웃을 만들 때 몇 가지 문제가 있습니다. 여러 네임 스페이스 오류가 있습니다. 제공하는 코드를 사용하는 방법에 대한 작은 블로그 게시물을 작성해 주시겠습니까?
— daniel_c05

항목을 항목 위로 드래그하는 동안 항목을 정렬하는 방식으로 코드를 수정할 가능성이 있습니까?
— Alex Semeniuk

@heycosmo GitHub 리포지토리에 액세스 할 수 있습니까? 오프라인 상태 인 것 같습니다 ...
— sdasdadas

8
bauerca 저장소는 더 이상 유지되지 않습니다. 이 포크는 더 활동적입니다 : github.com/JayH5/drag-sort-listview
— ecdpalma

21

이제 ItemTouchHelper 로 구현하기 RecyclerView가 매우 쉽습니다 . 에서 메소드를 재정의하십시오 .onMoveItemTouchHelper.Callback

 @Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;
}

이것에 대한 아주 좋은 튜토리얼은 medium.com에서 찾을 수 있습니다 : RecyclerView로 드래그 앤 스 와이프


18

이것에 대해 구글 사람들을 위해이 답변을 추가하고 있습니다 ..

최근 에 DevBytes ( ListView 셀 드래그 앤 재 배열 ) 에피소드가 있었으며이 작업을 수행하는 방법이 설명되어 있습니다.

당신은 그것을 찾을 수 있습니다 여기에 또한 샘플 코드를 볼 수 있습니다 여기에 .

이 코드는 기본적으로 셀 드래그 및 스와핑을 지원 dynamic listview하는 확장 기능 으로 코드를 만듭니다 listview. 따라서 DynamicListView기본 대신 사용할 수 ListView 있으며 드래그 앤 드롭으로 ListView를 구현했습니다.


1
DevBytes 구현을 사용할 때는 어댑터와 DynamicListView mush가 객체 배열 인 경우 동일한 인스턴스를 공유한다는 점에 유의하십시오. 그렇지 않으면 구현이 작동하지 않습니다. 이것은 정적 목록에는 문제가되지 않지만 로더에는 문제가 될 수 있습니다
— AAverin

현재 5.0 Android 버전에서 예제를 시도했습니다. 지금 몇 가지 문제가 있습니다 ...
— Torsten B

@TCA 네, 5.0에도 문제가 있습니다. 도와주세요.
— Manu

6

DragListView lib는 고도 애니메이션과 같은 커스텀 애니메이션을 아주 잘 지원하여 깔끔하게 처리합니다. 또한 정기적으로 유지 관리 및 업데이트됩니다.

사용 방법은 다음과 같습니다.

1 : 먼저 gradle에 lib 추가

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;
    }
}

자세한 정보는 https://github.com/woxblom/DragListView 를 참조하십시오.


5

DragSortListView가 잘 작동하지만 시작하는 것이 더 쉬울 수 있음을 알았습니다 . 다음은 인 메모리 목록과 함께 Android Studio에서 사용하는 방법에 대한 간단한 자습서입니다.

  1. 이것을 build.gradle앱 의 종속성에 추가하십시오 .

    compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
  2. 다음을 추가하거나 추가하여 드래그 핸들 ID에 대한 리소스를 만듭니다 values/ids.xml.

    <resources>
        ... possibly other resources ...
        <item type="id" name="drag_handle" />
    </resources>
  3. 즐겨 찾는 드래그 핸들 이미지가 포함 된 목록 항목의 레이아웃을 만들고 2 단계에서 만든 ID (예 :)에 해당 ID를 할당하십시오 drag_handle.

  4. 다음과 같이 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"/>
  5. 목록 항목보기를 렌더링 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);
  6. 항목을 놓을 때 재정렬하는 드롭 리스너를 설정하십시오.

        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();
            }
        });

3

나는 최근에 외부 의존성이 필요없는 드래그 정렬의 작동 구현을 제공하는 이 위대한 요점 을 우연히 발견 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();
}

이것은 가장 쉬운 구현 중 하나 인 것처럼 보이지만 나쁜 것처럼 보입니다 (행은 그냥 전환하고 실제로는 모양이 0이 아닙니다). 스크롤).
— Heinzlmaen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.