Android Liste Görünümü Sürükle ve Bırak sıralama


132

Bir liste görünümünde, kullanıcının sürükle ve bırak yöntemini kullanarak yeniden sıralayabilmesini istediğim kayıtların bir listesi var. Bunun diğer uygulamalarda uygulandığını gördüm, ancak bunun için bir eğitim bulamadım. Başkalarının da ihtiyaç duyduğu bir şey olmalı. Bunu yapmam için bana bir kod gösterebilecek biri var mı?


1
Sıralanabilir bir liste görünümü oluşturmaya yardımcı olabilecek bu öğreticiyi buldum . Henüz test etmedim ama video umut verici görünüyor
Alex

@Arkde şaka yok, yıllar sonra bu soruya hala bir cevabı kabul etmediler.
ArtOfWarfare

@ArtOfWarfare Sanırım soruyu soranın başına talihsiz bir şey gelmiş olabilir ... daha fazla faaliyete izin vermeme.
heycosmo

1
@heycosmo Olası ... SO profillerine göre, miannelle soruyu sorduktan sadece bir ay sonra ziyaret etti. Ayrıca, DSLV üzerinde harika bir çalışma ... Öğeleri kopyalamak için çift dokunma ve sürüklenirken öğenin gölgesini değiştirme gibi şeylere izin vermek için birkaç değişiklik yaptım (öğelerimin her birinin üzerinde satır numarası var, bu yüzden ben böylece satır numarası güncellemeleri sürüklendikçe güncellenebilir.) Sadece hacklenmişler, sınıftaki diğer her şeyden çok daha az zarifler, bu yüzden değişiklikleri GitHub'a göndermedim.
ArtOfWarfare

github.com/bauerca/drag-sort-listview Bunu kullanıyorum ve bir SATIR'ıLongClick of Listview'a sürüklemek mümkün mü?
Achin

Yanıtlar:


85

Bir süredir bunun üzerinde çalışıyorum. Doğru yapmak zor ve yaptığımı iddia etmiyorum ama şimdiye kadar mutluyum. Kodum ve birkaç demo şurada bulunabilir:

Önemli uygulama değişiklikleri yapılmış olmasına rağmen, kullanımı TouchInterceptor'a (kodun dayandığı) çok benzer .

DragSortListView, öğeleri sürüklerken ve karıştırırken pürüzsüz ve tahmin edilebilir kaydırma özelliğine sahiptir. Öğe karıştırmaları, sürüklenen / yüzen öğenin konumuyla çok daha tutarlıdır. Heterojen yükseklikteki liste öğeleri desteklenir. Sürükleyerek kaydırma özelleştirilebilir (uzun bir listede hızlı sürükleyerek kaydırmayı gösteriyorum - bir uygulama akla gelmiyor). Üstbilgiler / Altbilgilere saygı duyulur. vb.?? Bir göz at.


3
Çözümünüz bir cazibe gibi çalışıyor. Diğerlerinden çok daha iyi. Kaynak kodunuzun lisansı nedir? Apache 2.0?
Dariusz Bacinski

1
@heycosmo Demoda sağlanan görünümleri kullanarak uygulamamda bir düzen oluştururken birkaç sorun yaşıyorum. Birkaç ad alanı hatası, lütfen sağladığınız kodun nasıl kullanılacağına dair küçük bir blog yazısı yazabilir misiniz?
daniel_c05

Siz öğenizi üzerlerine sürüklerken, öğeleri yalnızca bırakarak sıralanmayacak şekilde kodu değiştirme imkanı var mı?
Alex Semeniuk

@heycosmo GitHub deponuzu erişilebilir hale getirebilir misiniz? Çevrimdışı gibi görünüyor ...
sdasdadas

8
Bauerca deposu artık korunmuyor. Bu çatal daha aktif: github.com/JayH5/drag-sort-listview
ecdpalma

21

Şimdi ItemTouchHelperRecyclerView ile uygulamak oldukça kolay . Sadece şu yöntemden geçersiz kıl :onMoveItemTouchHelper.Callback

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

Bu konuda oldukça iyi bir eğitim medium.com adresinde bulunabilir: RecyclerView ile Sürükle ve Kaydır


18

Bu cevabı bu konuda google yapanların amacı için ekliyorum ..

Son zamanlarda DevBytes'in ( ListView Hücre Sürükleme ve Yeniden Düzenleme ) bunun nasıl yapılacağını açıklayan bir bölümü vardı

Burada bulabilirsin, ayrıca örnek kod burada mevcuttur .

Bu kodun temelde yaptığı şey, hücre sürüklemeyi ve değiştirmeyi destekleyen bir dynamic listviewuzantı tarafından oluşturulmasıdır listview. Böylece DynamicListViewtemeliniz yerine kullanabilirsiniz ListView ve işte bu, Sürükle ve Bırak ile bir ListView uyguladınız.


1
DevBytes uygulamasını kullanırken, bağdaştırıcınızın ve DynamicListView mush'in aynı örneği if objects array paylaştığını unutmayın. Aksi takdirde uygulama çalışmayacaktır. Bu, statik listeler için bir sorun değil, ancak Yükleyiciler için bir sorun olabilir
AAverin

Örneği güncel 5.0 Android sürümünde denedim. Şimdi bazı sorunları var ...
Torsten B

@TCA Evet, benim de 5.0 ile ilgili sorunlarım var. Lütfen yardım et.
Manu

6

DragListView lib, yükseltme animasyonları gibi özel animasyonlar için çok güzel bir destekle bunu gerçekten düzgün yapıyor. Aynı zamanda düzenli olarak korunmakta ve güncellenmektedir.

İşte onu nasıl kullanıyorsun:

1: Önce not vermek için kitaplığı ekleyin

dependencies {
    compile 'com.github.woxthebox:draglistview:1.2.1'
}

2: xml'den liste ekle

<com.woxthebox.draglistview.DragListView
    android:id="@+id/draglistview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

3: Sürükleme dinleyicisini ayarlayın

mDragListView.setDragListListener(new DragListView.DragListListener() {
    @Override
    public void onItemDragStarted(int position) {
    }

    @Override
    public void onItemDragEnded(int fromPosition, int toPosition) {
    }
});

4: DragItemAdapter'dan geçersiz kılınmış bir adaptör oluşturun

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'dan genişleyen bir görüntü tutucu uygulayın

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

Daha ayrıntılı bilgi için https://github.com/woxblom/DragListView adresine gidin.


5

DragSortListView'un işe yaradığını buldum , ancak başlamak daha kolay olabilirdi. Bellek içi liste ile Android Studio'da kullanma hakkında kısa bir öğretici:

  1. Bunu build.gradleuygulamanızın bağımlılıklarına ekleyin:

    compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
  2. Aşağıdakileri oluşturarak veya ekleyerek sürükleme tutamacı kimliği için bir kaynak oluşturun values/ids.xml:

    <resources>
        ... possibly other resources ...
        <item type="id" name="drag_handle" />
    </resources>
    
  3. Favori sürükleme tutamacı görüntünüzü içeren bir liste öğesi için bir düzen oluşturun ve kimliğini 2. adımda oluşturduğunuz kimliğe atayın (örn. drag_handle).

  4. Aşağıdaki gibi bir DragSortListView düzeni oluşturun:

    <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. Liste öğesi görünümünüzü ArrayAdapteroluşturan bir getViewgeçersiz kılma ile bir türev ayarlayın .

        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. Öğeleri bırakıldıkça yeniden düzenleyen bir bırakma dinleyicisi ayarlayın.

        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

Kısa bir süre önce , harici bağımlılıklara ihtiyaç duymadan, sürükle sıralamanın çalışan bir uygulamasını sağlayan bu harika Öz'e rastladım ListView.


Temel olarak, özel Adaptörünüzü oluşturarak, ArrayAdapterbir iç sınıf olarak sizin ListView. Bu adaptörde onTouchListener, sürüklemenin başlangıcını işaret edecek olan Liste Öğelerinize bir tane ayarlar .

Bu Temelde, dinleyiciyi Liste Öğesinin düzeninin belirli bir kısmına (öğenin "tutacağı") ayarlarlar, böylece kişi yanlışlıkla herhangi bir kısmına basarak onu hareket ettirmez. Şahsen ben onLongClickListenerbunun yerine bir ile gitmeyi tercih ettim , ama buna karar vermek size kalmış. İşte o bölümden bir alıntı:

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

Bu aynı zamanda bir ekleme içerir onTouchListeneriçin ListViewbir öğe sürüklenen ise hangi kontroller, kolları takası ve geçersiz kılma ve sürükleme durumunu durdurur. Bu bölümden bir alıntı:

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

Son olarak, burada ne kadar stopDragve startDragetkinleştirme ve sürükleme işleminin devre dışı bırakılması işlemek, hangi gibi yöntemler bak:

public void startDrag(String string) {
    mPosition = -1;
    mSortable = true;
    mDragString = string;
    mAdapter.notifyDataSetChanged();
}

public void stopDrag() {
    mPosition = -1;
    mSortable = false;
    mDragString = null;
    mAdapter.notifyDataSetChanged();
}

Bu en kolay uygulamalardan biri gibi görünse de, kötü görünüyor (sadece satırlar değişiyor, aslında sıfır görünüm var), kötü hissettiriyor ve ekrana neredeyse sığmayan bir listede gezinmeyi imkansız hale getiriyor (bunun yerine sürekli olarak satırları değiştiriyorum ) kaydırma.
Heinzlmaen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.