with - web android studio




Scorri l'elemento ListView Da destra a sinistra mostra il pulsante Elimina (7)

È disponibile un'app che mostra un listview che combina sia lo scorrimento da eliminare sia il trascinamento per riordinare gli elementi. Il codice è basato sul codice di Chet Haase per lo swiping-to-delete e il codice di Daniel Olshansky per il trascinamento da riordinare.

Il codice di Chet cancella immediatamente un oggetto. L'ho migliorato rendendo la funzione più simile a Gmail, dove lo scorrimento rivela una vista dal basso che indica che l'elemento è stato eliminato ma fornisce un pulsante Annulla in cui l'utente ha la possibilità di annullare l'eliminazione. Il codice di Chet ha anche un bug in esso. Se nella lista sono presenti meno elementi rispetto all'altezza del listview e si elimina l'ultimo elemento, l'ultimo elemento sembra non essere cancellato. Questo è stato risolto nel mio codice.

Il codice di Daniel richiede di premere a lungo su un oggetto. Molti utenti trovano questo non intuitivo in quanto tende a essere una funzione nascosta. Invece, ho modificato il codice per consentire un pulsante "Sposta". Basta premere il pulsante e trascinare l'elemento. Questo è più in linea con il modo in cui l'app Google News funziona quando si riordinano argomenti di notizie.

Il codice sorgente insieme a un'app demo è disponibile all'indirizzo: https://github.com/JohannBlake/ListViewOrderAndSwipe

Chet e Daniel sono entrambi di Google.

Il video di Chet sull'eliminazione di elementi può essere visualizzato su: https://www.youtube.com/watch?v=YCHNAi9kJI4

Il video di Daniel sul riordino degli oggetti può essere visto su: https://www.youtube.com/watch?v=_BZIvjMgH-Q

Una quantità considerevole di lavoro è andata a incollare tutto questo insieme per fornire un'esperienza UI apparente, quindi mi piacerebbe un Like o Up Vote. Per favore, anche protagonista del progetto in Github.

Ho un ListView personalizzato che mostra l'elenco di parole che selezionano dal database. Quando faccio scorrere questo oggetto listview voglio mostrare il pulsante Elimina come immagine qui sotto. E quando premo quel pulsante viene cancellato dal Database e aggiorna la listview. m

Ho già trovato questo codice di esempio here . Ma ancora non funziona.


È una perdita di tempo implementare da zero questa funzionalità. Ho implementato la libreria consigliata da SalutonMondo e sono molto soddisfatta. È molto semplice da usare e molto veloce. Ho migliorato la libreria originale e ho aggiunto un nuovo listener di clic per il clic sull'elemento. Inoltre ho aggiunto la libreria impressionante di font ( http://fortawesome.github.io/Font-Awesome/ ) e ora puoi semplicemente aggiungere un nuovo titolo e specificare il nome dell'icona dal font fantastico.

Here il link github


Avevo lo stesso problema nel trovare una buona libreria per farlo. Alla fine, ho creato una libreria che può farlo: SwipeRevealLayout

Nel file gradle:

dependencies {
    compile 'com.chauthai.swipereveallayout:swipe-reveal-layout:1.4.0'
}

Nel tuo file xml:

<com.chauthai.swipereveallayout.SwipeRevealLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:mode="same_level"
    app:dragEdge="left">

    <!-- Your secondary layout here -->
    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />

    <!-- Your main layout here -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.chauthai.swipereveallayout.SwipeRevealLayout>

Quindi nel tuo file adattatore:

public class Adapter extends RecyclerView.Adapter {
  // This object helps you save/restore the open/close state of each view
  private final ViewBinderHelper viewBinderHelper = new ViewBinderHelper();

  @Override
  public void onBindViewHolder(ViewHolder holder, int position) {
    // get your data object first.
    YourDataObject dataObject = mDataSet.get(position); 

    // Save/restore the open/close state.
    // You need to provide a String id which uniquely defines the data object.
    viewBinderHelper.bind(holder.swipeRevealLayout, dataObject.getId()); 

    // do your regular binding stuff here
  }
}

Definisci un ViewPager nel tuo layout .xml:

<android.support.v4.view.ViewPager
    android:id="@+id/example_pager"
    android:layout_width="fill_parent"
    android:layout_height="@dimen/abc_action_bar_default_height" />

E poi, nella tua attività / frammento, imposta un adattatore per cercapersone personalizzato:

In un'attività:

protected void onCreate(Bundle savedInstanceState) {
    PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
    ViewPager pager = (ViewPager) findViewById(R.id.example_pager);

    pager.setAdapter(adapter);
    // pager.setOnPageChangeListener(this); // You can set a page listener here
    pager.setCurrentItem(0);
}

In un frammento:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_layout, container, false);

    if (view != null) {
        PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
        ViewPager pager = (ViewPager) view.findViewById(R.id.example_pager);

        pager.setAdapter(adapter);
        // pager.setOnPageChangeListener(this); // You can set a page listener here
        pager.setCurrentItem(0);
    }

    return view;
}

Crea la nostra classe di cercapersone personalizzata:

// setup your PagerAdapter which extends FragmentPagerAdapter
class PagerAdapter extends FragmentPagerAdapter {
    public static final int NUM_PAGES = 2;
    private CustomFragment[] mFragments = new CustomFragment[NUM_PAGES];
    public PagerAdapter(FragmentManager fragmentManager) {
        super(fragmentManager);
    }
    @ Override
    public int getCount() {
        return NUM_PAGES;
    }
    @ Override
    public Fragment getItem(int position) {
        if (mFragments[position] == null) {
               // this calls the newInstance from when you setup the ListFragment
            mFragments[position] = new CustomFragment();
        }
        return mFragments[position];
    }
}

Ho appena avuto il suo lavoro utilizzando il ViewSwitcher in un ListItem.

list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<ViewSwitcher
    android:id="@+id/list_switcher"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:inAnimation="@android:anim/slide_in_left"
    android:outAnimation="@android:anim/slide_out_right"
    android:measureAllChildren="false" >
    <TextView
        android:id="@+id/tv_item_name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="center_vertical"
        android:maxHeight="50dp"
        android:paddingLeft="10dp" />

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:clickable="false"
        android:gravity="center"
        >

    <Button
        android:id="@+id/b_edit_in_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Edit"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"

         />
    <Button
        android:id="@+id/b_delete_in_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Delete"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:background="@android:color/holo_red_dark"
        />
    </LinearLayout>
</ViewSwitcher>

In ListAdapter: implementa OnclickListeners per il pulsante Modifica e Elimina nel metodo getView (). Il problema qui è ottenere la posizione di ListItem su cui è stato fatto clic all'interno dei metodi onClick. per questo vengono utilizzati i metodi setTag () e getTag ().

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    final ViewHolder viewHolder;
    if (convertView == null) {
        viewHolder = new ViewHolder();
        convertView = mInflater.inflate(R.layout.list_item, null);
        viewHolder.viewSwitcher=(ViewSwitcher)convertView.findViewById(R.id.list_switcher);
        viewHolder.itemName = (TextView) convertView
                .findViewById(R.id.tv_item_name);
        viewHolder.deleteitem=(Button)convertView.findViewById(R.id.b_delete_in_list);
        viewHolder.deleteItem.setTag(position);
        viewHolder.editItem=(Button)convertView.findViewById(R.id.b_edit_in_list);
        viewHolder.editItem.setTag(position);
        viewHolder.deleteItem.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                fragment.deleteItemList((Integer)v.getTag());
            }
        });

        viewHolder.editItem.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                fragment.editItemList(position);
            }
        });
        convertView.setTag(viewHolder);
} else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    viewHolder.itemName.setText(itemlist[position]);
return convertView;  
}

Nel frammento, aggiungi un ascoltatore di gesti per rilevare il gesto di Fling:

public class MyGestureListener extends SimpleOnGestureListener {
    private ListView list;

    public MyGestureListener(ListView list) {
        this.list = list;
    }

    // CONDITIONS ARE TYPICALLY VELOCITY OR DISTANCE

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        // if (INSERT_CONDITIONS_HERE)

        ltor=(e2.getX()-e1.getX()>DELTA_X);
        if (showDeleteButton(e1))
        {
            return true;
        }
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
            float distanceX, float distanceY) {
        // TODO Auto-generated method stub
        return super.onScroll(e1, e2, distanceX, distanceY);
    }

    private boolean showDeleteButton(MotionEvent e1) {
        int pos = list.pointToPosition((int) e1.getX(), (int) e1.getY());
        return showDeleteButton(pos);
    }

    private boolean showDeleteButton(int pos) {

        View child = list.getChildAt(pos);
        if (child != null) {
            Button delete = (Button) child
                    .findViewById(R.id.b_edit_in_list);
            ViewSwitcher viewSwitcher = (ViewSwitcher) child
                    .findViewById(R.id.host_list_switcher);
            TextView hostName = (TextView) child
                    .findViewById(R.id.tv_host_name);
            if (delete != null) {
                    viewSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_in_left));
                    viewSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.slide_out_right));
                }

                viewSwitcher.showNext();
                // frameLayout.setVisibility(View.VISIBLE);
            }
            return true;
        }
        return false;
    }
}

Nel metodo onCreateView del Fragment,

GestureDetector gestureDetector = new GestureDetector(getActivity(),
            new MyGestureListener(hostList));
    hostList.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if (gestureDetector.onTouchEvent(event)) {
                return true;
            } else {
                return false;
            }

        }
    });

Questo ha funzionato per me. Dovrebbe perfezionarlo di più.


Ho attraversato tonnellate di librerie di terze parti per cercare di ottenere questo risultato. Ma nessuno di loro mostra l'esperienza di scorrevolezza e usabilità che volevo. Poi ho deciso di scriverlo da solo. E il risultato è stato, beh, mi è piaciuto molto. Condividerò il codice qui. Forse lo scriverò come una libreria che può essere incorporata in qualsiasi vista di riciclaggio in futuro. Ma per ora ecco il codice.

Nota: ho utilizzato la view Recycler e ViewHolder. Alcuni valori sono hardcoded quindi modificali in base alle tue esigenze.

  • row_layout.xml

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:orientation="horizontal">
        <Button
            android:id="@+id/slide_button_2"
            android:text="Button2"
            android:layout_width="80dp"
            android:layout_height="80dp" />
        <Button
            android:id="@+id/slide_button_1"
            android:text="Button1"
            android:layout_width="80dp"
            android:layout_height="80dp" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/chat_row_cell"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="horizontal"
        android:background="@color/white">
        <ImageView
            android:id="@+id/chat_image"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:layout_gravity="center"/>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <TextView
                    android:id="@+id/chat_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="@color/md_grey_800"
                    android:textSize="18sp"/>
                <TextView
                    android:id="@+id/chat_subtitle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="@color/md_grey_600"/>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
    

  • ChatAdaptor.java

    classe pubblica ChatAdaptor estende RecyclerView.Adapter {

    List<MXGroupChatSession> sessions;
    Context context;
    ChatAdaptorInterface listener;
    
    public interface ChatAdaptorInterface{
        void cellClicked(MXGroupChatSession session);
        void utilityButton1Clicked(MXGroupChatSession session);
        void utilityButton2Clicked(MXGroupChatSession session);
    }
    
    public ChatAdaptor(List<MXGroupChatSession> sessions, ChatAdaptorInterface listener, Context context){
        this.sessions=sessions;
        this.context=context;
        this.listener=listener;
    }
    
    @Override
    public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=(View)LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_row,null);
        ChatViewHolder chatViewHolder=new ChatViewHolder(view);
        return chatViewHolder;
    }
    
    @Override
    public void onBindViewHolder(ChatViewHolder holder, final int position) {
        MXGroupChatSession session=this.sessions.get(position);
        holder.selectedSession=session;
        holder.titleView.setText(session.getTopic());
        holder.subtitleView.setText(session.getLastFeedContent());
        Picasso.with(context).load(new File(session.getCoverImagePath())).transform(new CircleTransformPicasso()).into(holder.imageView);
    }
    
    @Override
    public int getItemCount() {
        return sessions.size();
    }
    
    public class ChatViewHolder extends RecyclerView.ViewHolder{
        ImageView imageView;
        TextView titleView;
        TextView subtitleView;
        ViewGroup cell;
        ViewGroup cellContainer;
        Button button1;
        Button button2;
    
        MXGroupChatSession selectedSession;
        private GestureDetectorCompat gestureDetector;
    
        float totalx;
        float buttonTotalWidth;
    
        Boolean open=false;
        Boolean isScrolling=false;
    
    
        public ChatViewHolder(View itemView) {
            super(itemView);
            cell=(ViewGroup) itemView.findViewById(R.id.chat_row_cell);
            cellContainer=(ViewGroup) itemView.findViewById(R.id.chat_row_container);
            button1=(Button) itemView.findViewById(R.id.slide_button_1);
            button2=(Button) itemView.findViewById(R.id.slide_button_2);
    
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    listener.utilityButton1Clicked(selectedSession);
                }
            });
    
            button2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    listener.utilityButton2Clicked(selectedSession);
                }
            });
    
            ViewTreeObserver vto = cellContainer.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    buttonTotalWidth = button1.getWidth()+button2.getWidth();
                }
            });
    
            this.titleView=(TextView)itemView.findViewById(R.id.chat_title);
            subtitleView=(TextView)itemView.findViewById(R.id.chat_subtitle);
            imageView=(ImageView)itemView.findViewById(R.id.chat_image);
            gestureDetector=new GestureDetectorCompat(context,new ChatRowGesture());
    
            cell.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if(gestureDetector.onTouchEvent(event)){
                        return true;
                    }
    
                    if(event.getAction() == MotionEvent.ACTION_UP) {
                        if(isScrolling ) {
                            isScrolling  = false;
                            handleScrollFinished();
                        };
                    }
                    else if(event.getAction() == MotionEvent.ACTION_CANCEL){
                        if(isScrolling ) {
                            isScrolling  = false;
                            handleScrollFinished();
                        };
                    }
                    return false;
                }
            });
        }
    
    
        public class ChatRowGesture extends GestureDetector.SimpleOnGestureListener {
    
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (!open){
                    listener.cellClicked(selectedSession);
                }
                return true;
            }
    
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
    
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                    isScrolling=true;
                    totalx=totalx+distanceX;
                    freescroll(totalx);
    
                return true;
            }
        }
    
        void handleScrollFinished(){
            if (open){
                if (totalx>2*buttonTotalWidth/3){
                    slideLeft();
                    totalx=buttonTotalWidth;
                }else{
                    slideRight();
                    totalx=0;
                }
            }else{
                if (totalx>buttonTotalWidth/3){
                    slideLeft();
                    totalx=buttonTotalWidth;
                }else{
                    slideRight();
                    totalx=0;
                }
            }
    
        }
    
        void slideRight(){
            TransitionManager.beginDelayedTransition(cellContainer);
            ViewGroup.MarginLayoutParams params;
            params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
            params.setMargins(0,0,0,0);
            cell.setLayoutParams(params);
            open=false;
        }
    
        void slideLeft(){
            TransitionManager.beginDelayedTransition(cellContainer);
            ViewGroup.MarginLayoutParams params;
            params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
            params.setMargins(((int)buttonTotalWidth*-1),0,(int)buttonTotalWidth,0);
            cell.setLayoutParams(params);
            open=true;
        }
        void freescroll(float x){
            if (x<buttonTotalWidth && x>0){
                int xint=(int)x;
                ViewGroup.MarginLayoutParams params;
                params=(ViewGroup.MarginLayoutParams) cell.getLayoutParams();
                params.setMargins(params.leftMargin,0,xint,0);
                cell.setLayoutParams(params);
            }
        }
    }
    

Spero che questo aiuti qualcuno !!


vedere lì il collegamento è stato molto bello e semplice. funziona bene ... tu non vuoi che nessuna libreria funzioni bene. clicca here

OnTouchListener gestureListener = new View.OnTouchListener() {
    private int padding = 0;
    private int initialx = 0;
    private int currentx = 0;
    private  ViewHolder viewHolder;

    public boolean onTouch(View v, MotionEvent event) {
        if ( event.getAction() == MotionEvent.ACTION_DOWN) {
            padding = 0;
            initialx = (int) event.getX();
            currentx = (int) event.getX();
            viewHolder = ((ViewHolder) v.getTag());
        }
        if ( event.getAction() == MotionEvent.ACTION_MOVE) {
            currentx = (int) event.getX();
            padding = currentx - initialx;
        }       
        if ( event.getAction() == MotionEvent.ACTION_UP || 
                     event.getAction() == MotionEvent.ACTION_CANCEL) {
            padding = 0;
            initialx = 0;
            currentx = 0;
        }
        if(viewHolder != null) {
            if(padding == 0) {
                v.setBackgroundColor(0xFF000000 );  
                if(viewHolder.running)
                    v.setBackgroundColor(0xFF058805);
            }
            if(padding > 75) {
                viewHolder.running = true;
                v.setBackgroundColor(0xFF00FF00 );  
                viewHolder.icon.setImageResource(R.drawable.clock_running);
            }
            if(padding < -75) {
                viewHolder.running = false;
                v.setBackgroundColor(0xFFFF0000 );  
            }

            v.setPadding(padding, 0,0, 0);
        }

        return true;
    }
};




swipe-gesture