web-dev-qa-db-ja.com

ListView項目を右から左にスワイプし、削除ボタンを表示します

データベースから選択した単語のリストを表示するカスタムListViewがあります。このリストビューアイテムをスワイプすると、下の画像のような[削除]ボタンが表示されます。そして、そのボタンを押すと、データベースから削除され、リストビューが更新されます。 mSwipe Listview item

私はすでにこのサンプルコードを調べています here 。しかし、まだ機能しません。

68
user3098538

編集:他のオプションの間に、あなたの問題を解決できる素敵なライブラリがあります: https://github.com/daimajia/AndroidSwipeLayout

36

私はグーグルを何度も検索して、最適なプロジェクトがswipmenulistview https://github.com/baoyongzhang/SwipeMenuListView githubであると見つけました。

15
SalutonMondo

私はそれを行うのに良いライブラリを見つけるのと同じ問題を抱えていました。最終的に、私はそれを行うことができるライブラリを作成しました: SwipeRevealLayout

Gradleファイル:

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

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>

次に、アダプターファイルで:

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
  }
}
15
Chau Thai

githubのデモ を作成しました。右から左にスワイプすると削除ボタンが表示され、ListViewからアイテムを削除してListViewを更新できます。

10
Lalit Poptani

ListItemでViewSwitcherを使用して彼の仕事を手に入れました。

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>

ListAdapter:getView()メソッドの[編集]ボタンと[削除]ボタンにOnclickListenersを実装します。ここでのキャッチは、onClickメソッド内でクリックされたListItemの位置を取得することです。これにはsetTag()および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;  
}

フラグメントに、ジェスチャーリスナーを追加して、フリングジェスチャーを検出します。

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

FragmentのonCreateViewメソッドで、

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

        }
    });

これは私のために働いた。もっと洗練すべきです。

5
user3316561

そこにリンクが非常に素晴らしく、簡単だった参照してください。正常に動作しています...正常に動作するライブラリは必要ありません。 こちら をクリックします

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

削除するスワイプとドラッグによるアイテムの並べ替えの両方を組み合わせたリストビューを示すアプリを利用できます。コードは、削除するためにスワイプするためのChet Haaseのコードと、並べ替えるためにドラッグするためのDaniel Olshanskyのコードに基づいています。

Chetのコードはアイテムをすぐに削除します。スワイプするとアイテムが削除されたことを示す下部ビューが表示され、ユーザーが削除を取り消すことができる[元に戻す]ボタンが表示されるGmailのように機能するように改善しました。 Chetのコードにもバグがあります。リストビューのアイテムの高さがリストビューの高さよりも少ない場合、最後のアイテムを削除すると、最後のアイテムは削除されないように見えます。これは私のコードで修正されました。

ダニエルのコードでは、アイテムを長押しする必要があります。多くのユーザーは、これが隠された機能になる傾向があるため、直感的ではないと感じています。代わりに、「移動」ボタンを許可するようにコードを変更しました。ボタンを押してアイテムをドラッグするだけです。これは、ニューストピックを並べ替えるときのGoogleニュースアプリの動作とほぼ一致しています。

ソースコードとデモアプリは次の場所で入手できます。 https://github.com/JohannBlake/ListViewOrderAndSwipe

チェットとダニエルは両方ともGoogleの出身です。

アイテムの削除に関するChetのビデオは、次の場所で見ることができます。 https://www.youtube.com/watch?v=YCHNAi9kJI4

アイテムの並べ替えに関するダニエルのビデオは、次の場所で見ることができます。 https://www.youtube.com/watch?v=_BZIvjMgH-Q

かなりの量の作業が、これらすべてを接着して、見かけのないUIエクスペリエンスを提供するために行われました。 Githubでプロジェクトにスターを付けてください。

2
AndroidDev

この機能をゼロから実装するのは時間の無駄です。 SalutonMondoが推奨するライブラリを実装し、非常に満足しています。使い方は非常に簡単で、非常に迅速です。元のライブラリを改善し、アイテムクリック用の新しいクリックリスナーを追加しました。また、フォントの素晴らしいライブラリ( http://fortawesome.github.io/Font-Awesome/ )を追加し、新しいアイテムタイトルを追加して、フォントawesomeからアイコン名を指定できるようになりました。

ここ はgithubリンクです

1
Popa Andrei

これを達成するために、私はたくさんのサードパーティのライブラリを試しました。しかし、それらのどれも私が欲しかった滑らかさと使いやすさの経験を示していません。それから私は自分でそれを書くことにしました。そして結果は、まあ、私はそれが大好きだった。ここでコードを共有します。たぶん、私はそれを将来どのリサイクラービューにも埋め込むことができるライブラリとして書くでしょう。しかし、今のところはコードです。

注:私はリサイクラービューとViewHolderを使用しています。一部の値はハードコーディングされているため、要件に応じて変更してください。

  • 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

    パブリッククラスChatAdaptorは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);
            }
        }
    }
    

これが誰かを助けることを願っています!!

1
Gitesh Agarwal

レイアウト.xmlでViewPagerを定義します。

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

次に、アクティビティ/フラグメントで、カスタムページャーアダプターを設定します。

アクティビティ内:

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

フラグメント内:

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

カスタムページャークラスを作成します。

// 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];
    }
}
1
Omer Leshem