在Android自定义列表视图中滑动显示按钮

3

我正在尝试实现在自定义列表视图中向右滑动显示按钮。目前我面临的问题是,我实现了在线上找到的onSwipeTouchListener,我能够看到滑动按钮。但是它不是一致的,我的意思是,如果我在一行上向右滑动,则按钮会在其他行中显示。这是我尝试过的方法。

我创建了一个用于保存视图的适配器

//TransactionAddDropViewHolder


        public static final class TransactionAddDropViewHolder {

    public View moveUpButton = null;
    public View moveDownButton = null;
    public View withdrawButton = null;
    public View reviewButton = null;

    public View approveButton = null;
    public View rejectButton = null;

    public LinearLayout addContainer = null;
    public LinearLayout dropContainer = null;



    public void swipeButtons() {
        addDropListView.setOnTouchListener(new OnSwipeTouchListener() {

            public void onSwipeRight() {
                withdrawButton.setVisibility(View.VISIBLE);
            }

            public void onSwipeLeft() {
                withdrawButton.setVisibility(View.INVISIBLE);
            }
        });
    }

    public void showUserButtons() {
        this.moveUpButton.setVisibility(View.VISIBLE);
        this.moveDownButton.setVisibility(View.VISIBLE);
        // this.withdrawButton.setVisibility(View.VISIBLE);
    }

    public void hideUserButtons() {
        this.moveUpButton.setVisibility(View.GONE);
        this.moveDownButton.setVisibility(View.GONE);
        // this.withdrawButton.setVisibility(View.GONE);
    } 

}

这是我的自定义视图,我在其中展示了onSwipeButton。
@Override
    public View getView(final int position, View convertView,
            ViewGroup parent) {

        final TransactionAddDrop addDropData = this.addDropList.get(position);

        TransactionAddDropViewHolder holder = null;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.fragment_pending_transaction_list_item, null);
            holder = new TransactionAddDropViewHolder();

holder.withdrawButton = convertView.findViewById(R.id.pendingTransactionItem_withdrawButton);
            holder.addContainer = (LinearLayout) convertView.findViewById(R.id.pendingTransactionItem_addContainer);
            **holder.swipeButtons();** 
            convertView.setTag(holder);
        } else {
            holder = (TransactionAddDropViewHolder) convertView.getTag();
            holder.swipeButtons(); 
        }

这是我的OnSwipeTouchListener类

    private final class GestureListener extends SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom();
                    } else {
                        onSwipeTop();
                    }
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}

添加XML布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.cbssports.nflapp.ffb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/swipeRight"
android:orientation="vertical" >

<LinearLayout
    android:id="@+id/claimlayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <LinearLayout
        android:id="@+id/claim"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="10dp" >

        <com.cbssports.nflapp.ffb.CustomText
            android:id="@+id/claimNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="1"
            android:textColor="#B4B4B5"
            android:textSize="36dp"
            app:typeface="oswald_regular" />
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/pendingPlayers"
        android:layout_width="200dp"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/tradeDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:orientation="horizontal"
            android:layout_toRightOf="@+id/claimlayout"
            android:paddingTop="5dp" >

            <com.cbssports.nflapp.ffb.CustomText
                android:id="@+id/pendingTransactionItem_teamName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#B4B4B5"
                android:textSize="9dp"
                app:typeface="oswald_regular" />

            <com.cbssports.nflapp.ffb.CustomText
                android:id="@+id/pendingTransactionItem_bidAmount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="#797979"
                android:text=""
                android:textColor="#ffffff"
                android:textSize="9dp" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/adddropView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tradeDate"
            android:layout_toRightOf="@+id/claimlayout"
            android:orientation="vertical" >

            <LinearLayout
                android:id="@+id/addViewContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal" >

                <com.cbssports.nflapp.ffb.CustomText
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:paddingRight="10dp"
                    android:text="ADD"
                    android:textColor="#797979"
                    android:textSize="15dp"
                    app:typeface="oswald_regular" />

                <LinearLayout
                    android:id="@+id/pendingTransactionItem_addContainer"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/adddropViewContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/claimlayout"
                android:orientation="horizontal" >

                <com.cbssports.nflapp.ffb.CustomText
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:paddingRight="10dp"
                    android:text="DROP"
                    android:textColor="#797979"
                    android:textSize="15dp"
                    app:typeface="oswald_regular" />

                <LinearLayout
                    android:id="@+id/pendingTransactionItem_dropContainer"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" />
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/pendingTransactionItem_userButtonContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_gravity="center_vertical"
        android:layout_toRightOf="@+id/pendingPlayers"
        android:gravity="center"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/pendingTransactionItem_moveUpButton"
                android:layout_width="20dp"
                android:layout_height="15dp"
                android:layout_margin="3dp"
                android:background="@drawable/gfx_up_arrow"
                android:padding="1dp"
                android:textColor="#ffffff"
                android:textSize="7sp"
                android:visibility="visible" />

            <Button
                android:id="@+id/pendingTransactionItem_moveDownButton"
                android:layout_width="20dp"
                android:layout_height="15dp"
                android:layout_margin="3dp"
                android:background="@drawable/gfx_down_arrow"
                android:padding="1dp"
                android:textColor="#ffffff"
                android:textSize="7sp"
                android:visibility="visible" />
        </LinearLayout>

        <ImageView
            android:id="@+id/pendingTransactionItem_withdrawButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="1dp"
            android:src="@drawable/ic_cancelclaim"
            android:visibility="gone" />

        <!-- Transaction Review -->

        <ImageView
            android:id="@+id/pendingTransactionItem_reviewButton"
            android:layout_width="38dp"
            android:layout_height="38dp"
            android:padding="1dp"
            android:src="@drawable/btn_review"
            android:visibility="gone" />
    </LinearLayout>
</LinearLayout>

添加一个问题。获取视图的总计数,但是想要在不同的布局中显示。这是我的onCreatedView函数。
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    fragmentPendingTrades = inflater.inflate(R.layout.fragment_transactions_pending, container, false);
    pendingTradesView = inflater;

    return fragmentPendingTrades;
}

    public void onViewCreated(final View view, final Bundle savedInstanceState) {

    this.addDropListView = (ListView) view.findViewById(R.id.transactions_pending_transactionsListView);
    this.addDropAdapter = new TransactionAddDropAdapter(pendingTradesView);
    this.addDropListView.setAdapter(this.addDropAdapter);
    this.emptyTransationsContainer = view.findViewById(R.id.transactions_pending_transactions_emptyContainer);



    TextView getTotalCount = (TextView) view.findViewById(R.id.transactions_pending_TransactionsAddDropCount);

    getTotalCount.setText(""+addDropListView.getCount());



}

我看到了你的问题(不止一个),但需要更多信息,请发布分配withdrawButton和整个TransactionAddDropViewHolder类的代码。 - Steven Byle
嗨,Steven,感谢回复。我刚刚更新了问题中的TransactionAddDropViewHolder类。 - dhiku
我仍然没有看到在findViewById中分配holder.withdrawButton的代码。你是否从getView方法中省略了一些代码? - Steven Byle
抱歉,在getView中错过了那一行。现在已添加withdrawbutton。 - dhiku
已在问题中添加了 XML 布局。谢谢。 - dhiku
显示剩余3条评论
1个回答

1
所以,我认为有两种方法可以实现:
  1. 监听整个列表的滑动,找出发生滑动的行,并显示/隐藏正确行的按钮。
  2. 监听每一行的滑动,并显示/隐藏该行的按钮。
目前,您正在对列表设置侦听器,但尝试应用适配器中附加的按钮的显示/隐藏。 在某种程度上,您正在执行每个解决方案的一半。 根据您的情况,我建议您选择第二种选项。
在您的TransactionAddDropViewHolder中,您需要获取行布局中根视图的引用,以便我们可以将OnSwipeTouchListener设置为它。
public static final class TransactionAddDropViewHolder {

    public View rootView = null;

    // Your other code

    public void swipeButtons() {
        rootView.setOnTouchListener(new OnSwipeTouchListener() {

            public void onSwipeRight() {
                withdrawButton.setVisibility(View.VISIBLE);
            }

            public void onSwipeLeft() {
                withdrawButton.setVisibility(View.INVISIBLE);
            }
        });
    }

    // Your other code

}

接下来,在您的getView方法中,更新它,以便您的TransactionAddDropViewHolder获得对布局中根View的引用。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    final TransactionAddDrop addDropData = this.addDropList.get(position);

    TransactionAddDropViewHolder holder = null;

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.fragment_pending_transaction_list_item, null);
        holder = new TransactionAddDropViewHolder();

        // Get a reference to the root of the row layout
        holder.rootView = convertView.findViewById(R.id.swipeRight); 

        holder.withdrawButton = convertView.findViewById(R.id.pendingTransactionItem_withdrawButton);
        holder.addContainer = (LinearLayout) convertView.findViewById(R.id.pendingTransactionItem_addContainer);

        holder.swipeButtons();
        convertView.setTag(holder);
    } else {
        holder = (TransactionAddDropViewHolder) convertView.getTag();
        holder.swipeButtons(); 
    }
}

您将面临另一个问题,即当用户继续滚动时,按钮将出现在其他行上,但只有在滑动时才会正确显示。这是因为ListView回收其行的View。我建议您执行以下两个操作之一:
  1. 当按钮出现后,用户再次开始滚动时,您可以再次隐藏它。这就是iOS在列表中使用“滑动删除”的方式。
  2. 使用布尔值存储数据对象中的行是否处于显示按钮模式,例如isDeleteShowing。然后在您的onSwipe回调中,将isDeleteShowing设置为true/false。最后,在您的getView中,根据该数据行的isDeleteShowing显示/隐藏按钮。
希望这些能够帮助您。

嗨Steven,太棒了...它能运行...只有一个快速问题。对视图来说它工作得很好。但是不稳定。比如手势中,向右滑动时,它可以运行,但大部分时间我必须要滑动三次。而向左滑动则需要六次以上。这是否意味着我需要更改阈值?谢谢 - dhiku
我认为可能发生的情况是,在整个滑动过程中,您的手指可能没有停留在行内。如果您的行很细,触摸坐标超出行界限,手势识别将停止在您越界的位置,通常导致无法看到滑动。除非使行更厚,否则我不确定您如何修复此问题。但是,如果您切换到选项1,则可以检查手势的起始和结束位置,如果在同一行中,则触发滑动。当然,这需要您重新编写一些代码。 - Steven Byle
谢谢。我会查看那个问题...还有一个最后的问题,关于在不同布局中获取视图的总数。我想打印行的totalCount,并在不同的布局中显示。请参见最后更新的问题。谢谢。 - dhiku
嗨 Steven,很抱歉再次提出这个问题。我正在尝试在滚动时重置按钮视图,但是我没有正确地实现。您能帮助我吗?谢谢。 - dhiku
我建议您创建一个新的问题,因为这是一个不同的问题。 - Steven Byle
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接