3

I am trying to implement, show the button on swipe right in the custom list view. Problem i am facing right now is, i implemented the onSwipeTouchListener which i found online. I could able to see the swipe button. But its not consistent, i mean if i swipe right on one row, button is displaying in some other row. This is what i tried.

i created an adapter for holding the view

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

}

And this is my Custom View where i am displaying the 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(); 
        }

And this is my OnSwipeTouchListener Class

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

Adding the XML Layout

<?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>

Adding one more question. getting the total Count of the view. But want to display in the different layout. Here is my 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());



}
dhiku
  • 1,818
  • 2
  • 22
  • 38

1 Answers1

1

So, this can be done 2 ways as I see it:

  1. Listen to swipes on the entire list, figure out which row the swiped occurred on, and show/hide the button for the correct row.
  2. Listen to swipes on each row, and show/hide the button for that row.

Right now you are setting the listener on the list, but trying to apply show/hide the button attached in the adapter. In a way, you are doing half of each solution. With what you have, I suggest you go with option #2.

In your TransactionAddDropViewHolder, you need to get a reference to the root View in the row layout, so we can set the OnSwipeTouchListener to it.

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

}

Next, in your getView method, update it so your TransactionAddDropViewHolder gets a reference to the root View in the layout.

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

There is one more issue you will have, the button will correctly show up when swiped, but if the user continues to scroll, it will appear on other rows. This is because ListView recycles its row's Views. I suggest you do either 2 things:

  1. When the user starts scrolling again after the button is present, you hide it again. This is what iOS does with "swipe to delete" in lists.
  2. Use a boolean to store in your data object if the row is in the mode where the button is visible, isDeleteShowing for example. Then in your onSwipe callbacks, you set isDeleteShowing to true/false. Lastly, in your getView, you show/hide of the button there depending on isDeleteShowing for that data row.

Hope this all helps.

Steven Byle
  • 13,149
  • 4
  • 45
  • 57
  • Hi Steven, Thats awesome ... it works ... just one more quick question. It works fine for the view. But its not consistent. Like in the gesture. When i swipe right, it works but most of the time i have to swipe like three times. And for swipe left i have to do most likely 6 times. Is that something i have to change the threshold? Thank you – dhiku Apr 25 '13 at 18:51
  • I think what may be happening is that your finger may not be staying inside the row during the entire swipe. If your rows are thin, and your touch coords go above or below the rows bounds, the gesture recognition will stop where you go out of bounds, usually resulting in no swipe being seen. I'm not sure how you can fix this other than making your rows thicker. However, if you switch to option #1, you can check where the gesture starts and ends, if it's in the same row, trigger a swipe then. Of course, this requires you to rework some code. – Steven Byle Apr 25 '13 at 19:13
  • Thank you. I will check on that one ... One more final question. about get the total Count of the view in the different layout. I want to print the totalCount of the row and want to display in the different layout. Please see the updated question in the end. Thank you. – dhiku Apr 25 '13 at 22:33
  • Since that is a different question you have added, and this one has been answered, please create a new question. – Steven Byle Apr 26 '13 at 00:17
  • Hi Steven, Sorry to come again for this question. I am trying to reset the button view when i scroll. I am not getting properly. Can you help me thank you. – dhiku Apr 28 '13 at 17:41
  • I suggest you create a new question, since this is a different issue. – Steven Byle Apr 28 '13 at 21:18
  • Thank you Steven here is my question http://stackoverflow.com/questions/16268200/how-can-i-handle-setonscrolllistener-for-custom-view-android – dhiku Apr 28 '13 at 21:38