Android UI How to - React to long-press listener








The following code shows how to React to long-press listener.

Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5

Example

Main layout xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <!-- Top Row of Draggable Items -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <ImageView
            android:id="@+id/image1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_launcher" />
        <ImageView
            android:id="@+id/image2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_launcher" />
        <ImageView
            android:id="@+id/image3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>

    <!-- Bottom Row of Drop Targets -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" >
        <com.examples.dragtouch.DropTargetView
            android:id="@+id/drag_target1"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_weight="1"
            android:background="#A00" />
        <com.examples.dragtouch.DropTargetView
            android:id="@+id/drag_target2"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_weight="1"
            android:background="#0A0" />
        <com.examples.dragtouch.DropTargetView
            android:id="@+id/drag_target3"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_weight="1"
            android:background="#00A" />
    </LinearLayout>

</RelativeLayout>

Main activity Java code

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.View.DragShadowBuilder;
public class MainActivity extends Activity implements OnLongClickListener {
  //from w ww  .  jav a 2 s  .c  o m
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //Attach long-press listener to each ImageView
        findViewById(R.id.image1).setOnLongClickListener(this);
        findViewById(R.id.image2).setOnLongClickListener(this);
        findViewById(R.id.image3).setOnLongClickListener(this);
    }

  @Override
  public boolean onLongClick(View v) {
    DragShadowBuilder shadowBuilder = new DragShadowBuilder(v);
//      DragShadowBuilder shadowBuilder = new DrawableDragShadowBuilder(v,
//              getResources().getDrawable(R.drawable.ic_launcher));
      v.startDrag(null, shadowBuilder, ((ImageView) v).getDrawable(), 0);    
    return true;
  }

}

/*
 * Copyright (C) 2011 by Mark Doffman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 */

class DrawableDragShadowBuilder extends DragShadowBuilder {
    private Drawable mDrawable;

    public DrawableDragShadowBuilder(View view, Drawable drawable) {
        super(view);
        // Set the drawable and apply a green filter to it
        mDrawable = drawable;
        mDrawable.setColorFilter(new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.MULTIPLY));
    }
    
    @Override
    public void onProvideShadowMetrics(Point shadowSize, Point touchPoint) {
        // Fill in the size
        shadowSize.x = mDrawable.getIntrinsicWidth();
        shadowSize.y = mDrawable.getIntrinsicHeight();
        // Fill in the location of the shadow relative to the touch.
        // Here we center the shadow under the finger.
        touchPoint.x = mDrawable.getIntrinsicWidth() / 2;
        touchPoint.y = mDrawable.getIntrinsicHeight() / 2;

        mDrawable.setBounds(new Rect(0, 0, shadowSize.x, shadowSize.y));
    }

    @Override
    public void onDrawShadow(Canvas canvas) {
        //Draw the shadow view onto the provided canvas
        mDrawable.draw(canvas);
    }
}

custom view java code

/* ww  w  .j  a  va 2  s. c  om*/

import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.View.OnDragListener;
import android.widget.ImageView;

public class DropTargetView extends ImageView implements OnDragListener {

    private boolean mDropped;

    public DropTargetView(Context context) {
        super(context);
        init();
    }

    public DropTargetView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DropTargetView(Context context, AttributeSet attrs, int defaultStyle) {
        super(context, attrs, defaultStyle);
        init();
    }

    private void init() {
        //We must set a valid listener to receive DragEvents
        setOnDragListener(this);
    }

    @Override
    public boolean onDrag(android.view.View v, DragEvent event) {
        PropertyValuesHolder pvhX, pvhY;
        switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
            //React to a new drag by shrinking the view
            pvhX = PropertyValuesHolder.ofFloat("scaleX", 0.5f);
            pvhY = PropertyValuesHolder.ofFloat("scaleY", 0.5f);
            ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY).start();
            //Clear the current drop image on a new event
            setImageDrawable(null);
            mDropped = false;
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            // React to a drag ending by resetting the view size
            // if we weren't the drop target.
            if (!mDropped) {
                pvhX = PropertyValuesHolder.ofFloat("scaleX", 1f);
                pvhY = PropertyValuesHolder.ofFloat("scaleY", 1f);
                ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY).start();
                mDropped = false;
            }
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            //React to a drag entering this view by growing slightly
            pvhX = PropertyValuesHolder.ofFloat("scaleX", 0.75f);
            pvhY = PropertyValuesHolder.ofFloat("scaleY", 0.75f);
            ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY).start();
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            //React to a drag leaving this view by returning to previous size
            pvhX = PropertyValuesHolder.ofFloat("scaleX", 0.5f);
            pvhY = PropertyValuesHolder.ofFloat("scaleY", 0.5f);
            ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY).start();
            break;
        case DragEvent.ACTION_DROP:
            // React to a drop event with a short animation keyframe animation
            // and setting this view's image to the drawable passed along with
            // the drag event
            
            // This animation shrinks the view briefly down to nothing
            // and then back.
            Keyframe frame0 = Keyframe.ofFloat(0f, 0.75f);
            Keyframe frame1 = Keyframe.ofFloat(0.5f, 0f);
            Keyframe frame2 = Keyframe.ofFloat(1f, 0.75f);
            pvhX = PropertyValuesHolder.ofKeyframe("scaleX", frame0, frame1,
                    frame2);
            pvhY = PropertyValuesHolder.ofKeyframe("scaleY", frame0, frame1,
                    frame2);
            ObjectAnimator.ofPropertyValuesHolder(this, pvhX, pvhY).start();
            //Set our image from the Object passed with the DragEvent
            setImageDrawable((Drawable) event.getLocalState());
            //We set the dropped flag to the ENDED animation will not also run
            mDropped = true;
            break;
        default:
            //Ignore events we aren't interested in
            return false;
        }
        //Declare interest in all events we have noted
        return true;
    }

}