【问题标题】:Swipe ListView item From right to left show delete button从右向左滑动 ListView 项目显示删除按钮
【发布时间】:2014-01-14 20:00:13
【问题描述】:

我有一个自定义 ListView 显示从数据库中选择的单词列表。当我滑动此列表视图项目时,我想显示删除按钮,如下图所示。当我按下该按钮时,它会从数据库中删除并刷新列表视图。 m

我已经查看了这个示例代码here。但是还是不行。

【问题讨论】:

  • 感谢 Rajesh CP。然而,实际上列表视图在适配器中膨胀了自定义布局。当然,如果我们想显示/隐藏删除按钮,我们必须在 Adpater 中完成,对吧?想知道我怎么能那样做。
  • 你检查过@luciano rodriguez 的答案吗?
  • 其实我不想要库,因为我觉得这个问题实现起来并不难,但我不知道该怎么做。
  • 我觉得代码数量不多但是不知道从哪个点入手。

标签: android android-listview swipe-gesture


【解决方案1】:

编辑: 在其他选项之间,有一个不错的库可以解决您的问题: https://github.com/daimajia/AndroidSwipeLayout

【讨论】:

  • 公平地说,他正在链接到 GitHub 上的库。你想让他把那些项目的源代码复制过来吗?并维护它?
  • 我不推荐Android SwipeListView。只是看看问题,太多的错误。
【解决方案2】:

我曾经在寻找一个好的库来做这件事时遇到同样的问题。最终,我创建了一个可以做到这一点的库: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
  }
}

【讨论】:

  • 无法解析“swipeRevealLayout”。你能帮帮我吗?
  • @Amarilindra : 添加第一个
  • 这是一个了不起的解决方案!我需要在我非常复杂的设计中稳定它,但我很震惊它的效果和它一样好。我有一个带有 gmail 风格的页面查看器,可以通过滑动来关闭。如果您尝试嵌套浏览器,或者您必须捕获滑动并丢失动画,这将不起作用。这是第一次尝试。 (虽然错过了约 20% 的滑动并且父母偷了它们,但我有一些调整可以尝试)
  • @Chau Thai 你的库是否与 androidx 兼容?我一直在我的 android 项目中使用你的库,我需要迁移到 androidx。请帮助我
【解决方案3】:

我在 google 上搜索了很多,发现最适合的项目是 github 上的 swipmenulistview https://github.com/baoyongzhang/SwipeMenuListView

【讨论】:

  • 我尝试在我的应用程序中将工作的 ListView 转换为 SwipeMenuListView。它不断崩溃,并在库代码中出现验证错误。 github页面上没有足够的文档让我弄清楚我做错了什么。
  • 继续尝试,我将这个项目与一个拖动排序列表视图库集成,它工作得很好。
  • 简单而伟大!我只花了几分钟就实现了!
  • 这个很有帮助
  • 这是一个很棒的库,但它不支持适配器或列表视图上的 notifiyDataSetChanged(),当我使用滑动菜单删除列表项时,我显然需要随后更新我的列表视图。
【解决方案4】:

我创建了一个demo on my github,其中包括从右向左滑动时会出现一个删除按钮,然后您可以从 ListView 中删除您的项目并更新您的 ListView。

【讨论】:

  • 能否请您许可您的代码,以便我们都可以合法地使用其中的一部分?谢谢:)
  • 这只是实现IOS设计。 which android does not like
  • 如果你的 github 页面上有一个 README.md 文件,其中包含一些正在运行的库的屏幕截图,那就太好了。
  • @Doomsknight Android 的原生电子邮件应用程序使用滑动删除,所以他们很难说第三方应用程序不能。
【解决方案5】:

我刚刚让他在 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() 方法中为 Edit 和 Delete 按钮实现 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;  
}

在片段中, 添加 Gesture Listener 以检测 Fling Gesture:

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

        }
    });

这对我有用。应该进一步完善它。

【讨论】:

  • 如果我刷了第 3 次没有视图然后第 4 次没有刷卡。另一个问题,我怎样才能只打开一个视图?
  • 我只是手动处理了这个。保存上次刷过的视图(prevItem)。当用户尝试滑动另一个视图 (currItem) 时,除了为 currItem 调用相同的视图之外,还为 prevItem 调用 viewSwitcher.showNext() 或 viewSwitcher.showPrevious()。这样,一次只会滑动一个视图。
  • 有一个我必须滚动的 ListView,对于某些孩子来说,要更改的 View 的识别失败。不过,用 list.getChildAt(pos-list.getFirstVisiblePosition()) 替换 list.getChildAt(pos) 效果很好。
【解决方案6】:

看到那里的链接非常好和简单。它工作正常... 你不希望任何图书馆都能正常工作。点击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;
    }
};

【讨论】:

  • 它是用来放置listview itme行的view holder类的吗?
  • 是的,你只需访问参考链接。它会向你解释。
【解决方案7】:

有一个应用程序演示了一个列表视图,该列表视图结合了滑动删除和拖动以重新排序项目。该代码基于 Chet Haase 的滑动删除代码和 Daniel Olshansky 的拖动重新排序代码。

Chet 的代码会立即删除一个项目。我对此进行了改进,使其功能更像 Gmail,滑动显示底部视图,指示该项目已删除,但提供了一个撤消按钮,用户可以在其中撤消删除。 Chet 的代码也有一个错误。如果列表视图中的项目少于列表视图的高度,并且您删除了最后一项,则最后一项似乎不会被删除。这已在我的代码中修复。

Daniel 的代码需要长按一个项目。许多用户发现这不直观,因为它往往是一个隐藏的功能。相反,我修改了代码以允许“移动”按钮。您只需按下按钮并拖动项目。这更符合 Google 新闻应用在您重新排序新闻主题时的工作方式。

源代码和演示应用程序可在以下位置获得: https://github.com/JohannBlake/ListViewOrderAndSwipe

Chet 和 Daniel 都来自 Google。

Chet 关于删除项目的视频可以在以下位置观看: https://www.youtube.com/watch?v=YCHNAi9kJI4

Daniel 关于重新订购商品的视频可在以下位置观看: https://www.youtube.com/watch?v=_BZIvjMgH-Q

为了提供无缝的 UI 体验,需要做大量工作才能将所有这些结合在一起,因此我会很感激您点赞或支持。也请在 Github 上为该项目加注星标。

【讨论】:

  • 删除了repo?
【解决方案8】:

我已经通过大量第三方库来尝试实现这一目标。但是它们都没有表现出我想要的流畅性和可用性体验。然后我决定自己写。结果是,嗯,我喜欢它。我将在这里分享代码。也许我会把它写成一个库,将来可以嵌入到任何回收器视图中。但现在这里是代码。

注意:我使用了回收站视图和 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);
            }
        }
    }
    

希望这对某人有所帮助!

【讨论】:

  • 谢谢。我不得不更改一些东西,但这比使用大型库更好更快。我最终对所有东西都使用了相对布局而不是线性布局。我还将按钮更改为内部带有 textview 的 RelativeLayout,这样我就可以让按下状态在按钮和主要部分上工作。然后在手势监听器和点击监听器上,我为点击反馈设置了主要部分的背景颜色。
【解决方案9】:

在你的布局 .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];
    }
}

【讨论】:

  • 你明白这个问题了吗?
  • @DiegoPalomar 此代码将为您提供完整的滑动。整个布局会改变,而不仅仅是一部分。我喜欢这个主意。有点帮助
【解决方案10】:

从头开始实施此功能会浪费时间。 我实现了 SalutonMondo 推荐的库,我很满意。 它使用起来非常简单,而且速度非常快。 我改进了原始库,并为项目单击添加了一个新的单击侦听器。 我还添加了 font awesome 库 (http://fortawesome.github.io/Font-Awesome/),现在您可以简单地添加一个新项目标题并从 font awesome 指定图标名称。

Here是github链接

【讨论】:

  • github页面上的库demo很漂亮。当我尝试从工作的 ListView 转换为它时,它一直在崩溃。 github 页面上没有足够的文档让我弄清楚我做错了什么。
【解决方案11】:

你可以使用这个代码

holder.img_close.setOnClickListener(new View.OnClickListener() {
      @Override
        public void onClick(View view) {
            holder.swipeRevealLayout.close(true);
            list.remove(position);
            notifyDataSetChanged();
      }});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多