William Da Silva
William Da Silva

Reputation: 723

OnLongClickListener in Button inside ListView

I'm having an issue, and an unusual behavior of a button. Actually it's two button plus (+) and minus (-) of a quantity field.

Those buttons are inside a ListView, and I can handle the OnClickListener without problem, but when I put the OnLongClickListener... I have two problems in two distinct ListViews:

1) All the information and behavior are normal, but when I LongClick the button, my Handler for automatically increase/decrease value start, but, I think, because the focuses he lost control and even when I release the button, the Handler don't stop. I used the same Handler in a dialog in same purpose, and worked fine.

2) In another ListView, when I put the OnLongClickListener, I have some fields (TextView, Spinner) stopping working.

Here is my Handler, it's a class Repeater with implements in OnTouchListener and OnLongClickListener:

public class Repeater implements OnTouchListener, OnLongClickListener{

    private View view; 

    private Repeater other_repeater;

    private int     REP_DELAY = 50; 
    private Handler repeatHandler = new Handler();

    private boolean mAutoRepeater = false;

    public Repeater(){}

    public Repeater(View view){
        this.setView(view);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(( event.getAction() == MotionEvent.ACTION_UP         || 
             event.getAction() == MotionEvent.ACTION_CANCEL     ||
             event.getAction() == MotionEvent.ACTION_HOVER_EXIT ||
             event.getAction() == MotionEvent.ACTION_OUTSIDE)
           && mAutoRepeater ){
            mAutoRepeater = false;
        }
        return false;
    }

    @Override
    public boolean onLongClick(View v) {
        if(getOther_repeater() != null){
            getOther_repeater().stop();
        }
        mAutoRepeater = true;
        repeatHandler.post( new RptUpdater() );
        return false;
    }

    private class RptUpdater implements Runnable {
        public void run() {
            if( mAutoRepeater ){
                getView().performClick();
                repeatHandler.postDelayed( new RptUpdater(), REP_DELAY );
            }
        }
    }

    public void stop(){
        mAutoRepeater = false;
    }

    public void setView(View view) {
        this.view = view;
    }

    public View getView() {
        return view;
    }

    public void setOther_repeater(Repeater other_repeater) {
        this.other_repeater = other_repeater;
    }

    public Repeater getOther_repeater() {
        return other_repeater;
    }
}

I have my CustomAdapter for each ListView, with almost a thousand lines... the code below it's where I set the Repeater:

            Repeater qt_produto_menos_repeater = new Repeater(viewHolder.qt_produto_menos);

            viewHolder.qt_produto_menos.setOnTouchListener    (qt_produto_menos_repeater);
            viewHolder.qt_produto_menos.setOnLongClickListener(qt_produto_menos_repeater);

            Repeater qt_produto_mais_repeater = new Repeater(viewHolder.qt_produto_mais);

            viewHolder.qt_produto_mais.setOnTouchListener    (qt_produto_mais_repeater);
            viewHolder.qt_produto_mais.setOnLongClickListener(qt_produto_mais_repeater);

            qt_produto_menos_repeater.setOther_repeater(qt_produto_mais_repeater);
            qt_produto_mais_repeater.setOther_repeater(qt_produto_menos_repeater);

This is my ListView in the xml:

    <ListView
            android:id="@+id/lv_resultado_produtos"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:divider="@color/Black"
            android:dividerHeight="1dip"
            android:fastScrollEnabled="true"
            android:scrollX="0dip"
            android:scrollY="0dip"
            android:scrollbarSize="22dip"
            android:scrollbarStyle="outsideOverlay" 
     />

I don't know why the OnClickListener of the buttons are working fine and the OnLongClick don't.

Please some help, I'm stuck on this for a few days.

[EDIT]

The LongClick works fine, but the Repeater can't get the "UP" / "CANCEL" action, there is, when I release the button. The OnTouchListener need to know for stop the Handler, even when all the logic is inside the CustomAdapter. And this is for one ListView, the other is getting crazy the other fields, but if I can solve the "release button" problem, I will be glad!

[EDIT2]

Finally I isolated the problem. The second ListView I solved the case, my Repeater was called after all the logic, I don't know why, but this get the list crazy!

And the first problem, I discovered the notifyDataSetChanged() messing up everything, The button loose the focus when notify...() is called, and the Repeater never get the "command" to stop increase/decrease, I partially solved changing this:

        if( mAutoRepeater ){
            getView().performClick();
            repeatHandler.postDelayed( new RptUpdater(), REP_DELAY );
        }

To this, in the Repeater:

        if( view.isPressed() ){
            getView().performClick();
            repeatHandler.postDelayed( new RptUpdater(), REP_DELAY );
        }

So, now, he stop increase/decrease when notify...() is called, but that doesn't is the behavior we want. Someone know something for "delay" the notify? Or set the focus again to the button (and keep pressed) if the user is still pressing the button?

Upvotes: 2

Views: 663

Answers (1)

canova
canova

Reputation: 3975

I tried this in getView() of the adapter and it is working properly without any bugs for listview and button functionality:

testButton.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        Toast.makeText(context, "long click achieved", Toast.LENGTH_SHORT).show();
        testButton.setVisibility(View.INVISIBLE);
        return false;
    }
});

can you try writing the onlongclick functionality in getView to see if it is working like that? By the way there are no focus instuctions on my test button and list xml files:

<Button
    android:id="@+id/test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button" />

and the list:

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</ListView>

Upvotes: 1

Related Questions