ListView item LongClick state for selector

2019-02-03 19:52发布

On the default ListViews if you long press on an item the background fades from dark blue to light blue(on Galaxy Tab. Its orange to light orange on some other devices) during the time it takes to register a LongClick. I am assuming this is done somehow with a selector but thus far I've only seen how to use selectors for state:selected, state:focused, and state:pressed.

This page doesn't seem to show anything about a LongClick state so perhaps my assumption that this is accomplished with a selector is incorrect?

Can anyone fill me in on how the default ListView gets this effect and how I can apply it to other views?

3条回答
趁早两清
2楼-- · 2019-02-03 20:17

http://developer.android.com/guide/topics/ui/menus.html#context-menu

When the user performs a long-press on an item in a ListView and the list is registered to provide a context menu, the list item signals to the user that a context menu is available by animating its background color—it transitions from orange to white before opening the context menu. (The Contacts application demonstrates this feature.)

So its an animation that is used. I believe it uses the View's own default On...() methods to display it. You may need to worry about giving it clickable="true" or longClickable="true" attributes.

查看更多
男人必须洒脱
3楼-- · 2019-02-03 20:17

In addition to your OnTouchListener, you can use a Runnable to revert back the background to it's original state so that you don't need to explicitly do it in the OnLongClick handler.

Handler myHandler = new Handler();
...
transition.startTransition(ViewConfiguration.getLongPressTimeout());
ResetBG r = new ResetBG(transition);
myHandler.postDelayed(r, ViewConfiguration.getLongPressTimeout());

where ResetBG is:

class ResetBG implements Runnable {
    protected TransitionDrawable myTran;

    public Runnable(TransitionDrawable tran) {
        myTran = tran;
    }

    public void run() {
        myTran.resetTransition();
    }
}
查看更多
不美不萌又怎样
4楼-- · 2019-02-03 20:19

So it turned out to be a little bit more difficult than I had thought but I have it working almost correctly now.

Here is the OnTouchListener I ended up using:

listOnTouchListener = new OnTouchListener() {
         public boolean onTouch(View v, MotionEvent me){
             if (me.getAction() == MotionEvent.ACTION_DOWN){
                 //This means a finger has come down on top of our view
                 //We are going to start the animation now.
                 Log.i(myTag, "Action Down");
                 Context mContext = getApplicationContext();
                 Resources res = mContext.getResources();
                 TransitionDrawable transition = (TransitionDrawable) res.getDrawable(R.drawable.listtransition);
                 v.setBackgroundDrawable(transition);
                 //LongClick took approx. 510-530 milliseconds to register after OnTouch. So I set the duration at 500 millis.
                 transition.startTransition(500);
             }else if (me.getAction() == MotionEvent.ACTION_UP){
                 //This means we didn't hold long enough to get a LongClick
                 //Set the background back to the normal one.
                 v.setBackgroundResource(R.drawable.bubblelight);

             }else if (me.getAction() == MotionEvent.ACTION_MOVE){
                 //Do Nothing
             }else if (me.getAction() == MotionEvent.ACTION_CANCEL){
                 Log.i(myTag, "Action Cancel");
                 //This means we are scrolling on the list, not trying to longpress
                 //So set the background back to the normal one.
                 v.setBackgroundResource(R.drawable.bubblelight);
             }
             return false;

         }
     };

I also used an OnLongClickListener inside this I set the background back to the normal one.

Here is the Transition XML:

<transition xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/bubblelight1" />
  <item android:drawable="@drawable/bubbledark" />
</transition>

You may be asking whats with the bubblelight1? More on that in a moment.

Here is the getView() Method I use inside my adapter to return the views that get displayed in the List:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        v = convertView;
        if (v == null) {
            LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.row, null);
        }
        Status s = items.get(position);
        if (s != null) {
            v.setOnTouchListener(listOnTouchListener);
            v.setOnLongClickListener(listOnLongClickListener);
            tweetTxt = (TextView) v.findViewById(R.id.tweetTxt);
            timeTxt = (TextView) v.findViewById(R.id.timeTxt);
            if (tweetTxt != null) {
                tweetTxt.setText(s.getText());
                tweetTxt.setOnTouchListener(gestureListener);
            }
            if(timeTxt != null){
                timeTxt.setText(getTimeFromNow(s.getCreatedAt().getTime()));
                //timeTxt.setText(s.getCreatedAt().toLocaleString());
            }
        }
        LinkifyWithTwitter.addLinks(tweetTxt, Linkify.ALL);
        return v;
    }

v.setOnTouchListener(listOnTouchListener); and v.setOnLongClickListener(listOnLongClickListener); are the lines that set up the view with the Listeners that I've shown above.

Now about the bubblelight1. bubblelight and bubbledark are the nine patch images I am using when I tried this the first time whenever the transition started instead of the background transitioning from bubblelight to bubbledark, bubblelight would grow bigger and bubbledark would appear inside of bubblelight. So I had a big bubble that was light, a smaller bubble that was dark, then the text inside that. To fix this issue I made a copy of bubblelight and made the bottom and right edges of the ninepatch completely filled in. I just had to do the first image in the transition though, not the second. If I did the second image that way then my text would jump out of the bubble and some it would get shown over the top and along the sides of the bubble. I am not entirely sure why this was happening, or why this fix happened to work. But It does the job for now.

查看更多
登录 后发表回答