Android view property animation - android

Hello Community I was wondering if you could help me in the following question. I am working on a project where I need to be able to move a bitmap a certain distance when I touch it. (step 2 in the snapshot) However,on reaching the boundary the image should be wrapped to the other side as shown in Step 3.
I read the property animator and how it allows tweeting of views but what I don't understand is what kind of layout should I use. Should I use a RelativeLayout or LinearLayout? or Should I use a canvas?
How do I mask the parent view (view B in the snapshot) to achieve the view wrapping effect.
Thank you kindly,

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.Button;
public class AnticiButton extends Button {
private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator(8);
private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
private static final OvershootInterpolator sOvershooter = new OvershootInterpolator();
private static final DecelerateInterpolator sQuickDecelerator = new DecelerateInterpolator();
private float mSkewX = 0;
ObjectAnimator downAnim = null;
boolean mOnLeft = true;
RectF mTempRect = new RectF();
public AnticiButton(Context context) {
super(context);
init();
}
public AnticiButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public AnticiButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setOnTouchListener(mTouchListener);
setOnClickListener(new OnClickListener() {
public void onClick(View v) {
runClickAnim();
}
});
}
#Override
public void draw(Canvas canvas) {
if (mSkewX != 0) {
canvas.translate(0, getHeight());
canvas.skew(mSkewX, 0);
canvas.translate(0, -getHeight());
}
super.draw(canvas);
}
private void runPressAnim() {
downAnim = ObjectAnimator.ofFloat(this, "skewX", mOnLeft ? .5f : -.5f);
downAnim.setDuration(2500);
downAnim.setInterpolator(sDecelerator);
downAnim.start();
}
private void runClickAnim() {
// Anticipation
ObjectAnimator finishDownAnim = null;
if (downAnim != null && downAnim.isRunning()) {
// finish the skew animation quickly
downAnim.cancel();
finishDownAnim = ObjectAnimator.ofFloat(this, "skewX",
mOnLeft ? .5f : -.5f);
finishDownAnim.setDuration(150);
finishDownAnim.setInterpolator(sQuickDecelerator);
}
ObjectAnimator moveAnim = ObjectAnimator.ofFloat(this,
View.TRANSLATION_X, mOnLeft ? 400 : 0);
moveAnim.setInterpolator(sLinearInterpolator);
moveAnim.setDuration(150);
ObjectAnimator skewAnim = ObjectAnimator.ofFloat(this, "skewX",
mOnLeft ? -.5f : .5f);
skewAnim.setInterpolator(sQuickDecelerator);
skewAnim.setDuration(100);
// and wobble it
ObjectAnimator wobbleAnim = ObjectAnimator.ofFloat(this, "skewX", 0);
wobbleAnim.setInterpolator(sOvershooter);
wobbleAnim.setDuration(150);
AnimatorSet set = new AnimatorSet();
set.playSequentially(moveAnim, skewAnim, wobbleAnim);
if (finishDownAnim != null) {
set.play(finishDownAnim).before(moveAnim);
}
set.start();
mOnLeft = !mOnLeft;
}
private void runCancelAnim() {
if (downAnim != null && downAnim.isRunning()) {
downAnim.cancel();
ObjectAnimator reverser = ObjectAnimator.ofFloat(this, "skewX", 0);
reverser.setDuration(200);
reverser.setInterpolator(sAccelerator);
reverser.start();
downAnim = null;
}
}
private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (isPressed()) {
performClick();
setPressed(false);
break;
}
// No click: Fall through; equivalent to cancel event
case MotionEvent.ACTION_CANCEL:
// Run the cancel animation in either case
runCancelAnim();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
boolean isInside = (x > 0 && x < getWidth() &&
y > 0 && y < getHeight());
if (isPressed() != isInside) {
setPressed(isInside);
}
break;
case MotionEvent.ACTION_DOWN:
setPressed(true);
runPressAnim();
break;
default:
break;
}
return true;
}
};
public float getSkewX() {
return mSkewX;
}
public void setSkewX(float value) {
if (value != mSkewX) {
mSkewX = value;
invalidate(); // force button to redraw with new skew value
invalidateSkewedBounds(); // also invalidate appropriate area of parent
}
}
private void invalidateSkewedBounds() {
if (mSkewX != 0) {
Matrix matrix = new Matrix();
matrix.setSkew(-mSkewX, 0);
mTempRect.set(0, 0, getRight(), getBottom());
matrix.mapRect(mTempRect);
mTempRect.offset(getLeft() + getTranslationX(), getTop() + getTranslationY());
((View) getParent()).invalidate((int) mTempRect.left, (int) mTempRect.top,
(int) (mTempRect.right +.5f), (int) (mTempRect.bottom + .5f));
}
}
}
Add your xml layout:
<view
class="com.example.android.anticipation.AnticiButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AnticiButton"/>
I hope this will help

Related

Selection overlay when dragging over views

I'm trying to build a view that works like the calendar agenda view (a vertical list of hours that user can select by dragging) but I'm stuck at the part where user begins to start pressing on the screen and dragging his finger over the hour rows to select them. How can I make am overlay representing the selection over the views that represents the hours and expand/shrink it as user drags the selection?
My current interface is composed of a vertical oriented LinearLayout that contains empty TextViews as placeholders that represents the hours of the day.
This is how my screen looks like:
Each green column is the LinearLayout with the TextViews representing the slots. I want to allow the user to start pressing on one of the slots and dragging down to make the selection and while the dragging is in progress to have an overlay that shrinks/expands to reflect the selection.
I've managed to solve it by extending the LinearLayout and hooking into the drawing mechanism like this:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class AvailabilityCalendarColumnLayout extends LinearLayout{
private Drawable overlay;
public AvailabilityCalendarColumnLayout(Context context) {
super(context);
setWillNotDraw(false);
}
public AvailabilityCalendarColumnLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
setWillNotDraw(false);
}
public AvailabilityCalendarColumnLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(overlay != null) {
overlay.draw(canvas);
}
}
public boolean startSelectionOverlay(View startingView) {
if(startingView == null) {
return false;
}
overlay = getResources().getDrawable(R.drawable.overlay);
float[] l = new float[2];
l[0] = startingView.getX();
l[1] = startingView.getY();
int w = startingView.getWidth();
int h = startingView.getHeight();
overlay.setBounds((int) l[0], (int) l[1], (int) l[0] + w, (int) l[1] + h);
invalidate();
return true;
}
private void extendSelectionOverlay(View endView) {
if(endView == null) {
return;
}
float[] l = new float[2];
l[0] = endView.getX();
l[1] = endView.getY();
int w = endView.getWidth();
int h = endView.getHeight();
Rect r = overlay.getBounds();
r.bottom = (int)l[1] + h;
overlay.setBounds(r);
invalidate();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
float[] pos = new float[2];
pos[0] = ev.getX();
pos[1] = ev.getY();
if(action == MotionEvent.ACTION_DOWN && overlay == null) {
View view = getChildViewUnderPosition(pos);
if(view != null) {
startSelectionOverlay(view);
}
}
if(action == MotionEvent.ACTION_MOVE && overlay != null) {
View view = getChildViewUnderPosition(pos);
extendSelectionOverlay(view);
}
if(action == MotionEvent.ACTION_UP && overlay != null) {
endSelectionOverlay();
invalidate();
}
return true;
}
private View getChildViewUnderPosition(float[] pos) {
int num = getChildCount();
View v;
for(int x = 0; x < num; x++) {
v = getChildAt(x);
if(v.getX() <= pos[0] && (v.getX() + v.getWidth()) >= pos[0] && v.getY() <= pos[1] && (v.getY() + v.getHeight()) >= pos[1] && !v.isSelected()) {
return v;
}
}
return null;
}
private void endSelectionOverlay() {
overlay = null;
invalidate();
}
}

Send Value to Main from extended View

I have this activity that detects Multi-Touch and counts each instance that the device is tapped over 3 times. What I want is to do a check in Main to see if it reaches the limit that have been set.
Main Activity
package com.test.multitouch;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// DETECT more than 20 counts here and display a toast
}
Custom View which extends view
package com.test.multitouch;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
#SuppressLint("ClickableViewAccessibility")
public class custom_view extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
final int MAX_NUMBER_OF_POINT = 4;
float[] x = new float[MAX_NUMBER_OF_POINT];
float[] y = new float[MAX_NUMBER_OF_POINT];
boolean[] touching = new boolean[MAX_NUMBER_OF_POINT];
int count = 0;
long cur = System.currentTimeMillis();
long dur = 30000;
long fut = cur + dur;
public custom_view(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public custom_view(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public custom_view(Context context) {
super(context);
init();
}
void init() {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(40);
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < MAX_NUMBER_OF_POINT; i++) {
if (touching[i]) {
switch (i) {
case 1:
paint.setColor(Color.BLUE);
break;
case 2:
paint.setColor(Color.RED);
break;
case 3:
paint.setColor(Color.YELLOW);
break;
case 4:
paint.setColor(Color.GREEN);
break;
}
canvas.drawCircle(x[i], y[i], 70f, paint);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = (event.getAction() & MotionEvent.ACTION_MASK);
int pointCount = event.getPointerCount();
if (pointCount > 3) {
Log.i("LOG", "register multi touch");
count++;
if (count > 20) {
//SEND BACK TO MAIN TO SAY IT HAS BEEN ACHIEVED
}
}
for (int i = 0; i < pointCount; i++) {
int id = event.getPointerId(i);
if (id < MAX_NUMBER_OF_POINT) {
x[id] = (int) event.getX(i);
y[id] = (int) event.getY(i);
if ((action == MotionEvent.ACTION_DOWN)
|| (action == MotionEvent.ACTION_POINTER_DOWN)
|| (action == MotionEvent.ACTION_MOVE)) {
touching[id] = true;
} else {
touching[id] = false;
}
}
}
invalidate();
return true;
}
}
Your custom view has a reference to the context it's attached to. I assume this view is running in the same activity you are trying to reference. You can get the reference to the activity as follows:
MainActivity mainActivity = (MainActivity) custom_view.this.getContext();
I also assumed you are calling this from inside your onTouchListener. You need to reference the "this" to get to the outterclass instance, otherwise this will refer to the instance of your onTouchListener class instead. Also, you should capitalize class names, so you can recognize from the capitalization whether we are referring to an instance or class definition.
Once you have the reference, you can call some function on main Activity to update it.
mainActivity.callSomeFunction();

Android Drag and Drop functionality

Is there some way to implement drag and drop functionality in API 8 Android?
Looked here, but it appears after API 11.
I need to drag view from one LinearLayout to another. Ho can i implement this on API 8?
Try like this
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
ListView source = null;
TextView target1 = null;
TextView target2 = null;
TextView target3 = null;
String[] listItems = {"Samsung", "Apple", "Google", "Nokia"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
source = (ListView)findViewById(R.id.dragSource);
target1 = (TextView) findViewById(R.id.dragTarget1);
target2 = (TextView) findViewById(R.id.dragTarget2);
target3 = (TextView) findViewById(R.id.dragTarget3);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listItems);
source.setAdapter(adapter);
// Start Drag
source.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String item = listItems[position];
ClipData data = ClipData.newPlainText("DragIt", item);
source.startDrag(data, new MyShadowBuilder(view), null, 0);
}
});
// Handle Drag
target1.setOnDragListener(new MyDragListener());
target2.setOnDragListener(new MyDragListener());
target3.setOnDragListener(new MyDragListener());
}
// Drag Shadow
private class MyShadowBuilder extends DragShadowBuilder {
public MyShadowBuilder(View v) {
super(v);
}
#Override
public void onDrawShadow(Canvas canvas) {
// Set Drag image background or anything you want
int width = getView().getWidth();
int height = getView().getHeight();
Paint paint = new Paint();
paint.setColor(0x55858585);
canvas.drawRect(new Rect(0, 0, width, height), paint);
super.onDrawShadow(canvas);
}
#Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
int width = getView().getWidth();
int height = getView().getHeight();
shadowSize.set(width, height);
shadowTouchPoint.set(width/2, height);
}
}
// Drag Listener
private class MyDragListener implements OnDragListener {
private final int DEFAULT_BG_COLOR = 0xFF858585;
private final int HIGHLIGHT_BG_COLOR = 0xFF0000FF;
#Override
public boolean onDrag(View v, DragEvent event) {
if(event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
v.setBackgroundColor(HIGHLIGHT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DRAG_EXITED) {
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
else if(event.getAction() == DragEvent.ACTION_DROP) {
// Perform drop
ClipData clip = event.getClipData();
ClipData.Item item = clip.getItemAt(0);
String text = item.getText().toString();
((TextView) v).setText(text);
v.setBackgroundColor(DEFAULT_BG_COLOR);
}
// Send true to listen All Drag Events.
return true;
}
}
}
XML is like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="161dp"
android:layout_height="fill_parent"
android:background="#FF858585"
android:orientation="vertical" >
<TextView
android:id="#+id/dragTarget1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/dragTarget2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/dragTarget3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.04"
android:text="Drop Here"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/dragSource"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Try another approach by using WindowManager :
package com.example.cooldraganddrop;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`
private static final int ITEM_HOVER_DELAY = 450;
private int mDragPointX;
private int mDragPointY;
private int mDragOffsetX;
private int mDragOffsetY;
private int mDragPosition = AdapterView.INVALID_POSITION;
private int mDropPosition = AdapterView.INVALID_POSITION;
private int mCurrentPosition = AdapterView.INVALID_POSITION;
private Runnable mDelayedOnDragRunnable = null;
ScrollingStrategy mScrollingStrategy = null;
WindowManager mWindowManager = null;
WindowManager.LayoutParams mWindowParams = null;
private ImageView mDragImageView = null;
private boolean mDragAndDropStarted = false;
private DragAndDropListener mDragAndDropListener = null;
private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;
public static interface OnTrackTouchEventsListener {
void trackTouchEvents(final MotionEvent motionEvent);
};
public static interface DragAndDropListener {
void onDragItem(int from);
void onDraggingItem(int from, int to);
void onDropItem(int from, int to);
boolean isDragAndDropEnabled(int position);
}
public CoolDragAndDropGridView(Context context) {
super(context);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
private void initialize() {
setOnTouchListener(this);
setChildrenDrawingOrderEnabled(true);
}
public void startDragAndDrop() {
mDragAndDropStarted = true;
}
public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {
mDragAndDropListener = dragAndDropListener;
}
private void destroyDragImageView() {
if (mDragImageView != null) {
mWindowManager.removeView(mDragImageView);
BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
if (bitmapDrawable != null) {
final Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
mDragImageView.setImageDrawable(null);
mDragImageView = null;
}
}
private ImageView createDragImageView(final View v, final int x, final int y) {
v.destroyDrawingCache();
v.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());
mDragPointX = x - v.getLeft();
mDragPointY = y - v.getTop();
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.alpha = 0.7f;
mWindowParams.windowAnimations = 0;
ImageView iv = new ImageView(getContext());
iv.setBackgroundColor(Color.parseColor("#ff555555"));
iv.setImageBitmap(bm);
mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
mWindowManager.addView(iv, mWindowParams);
return iv;
}
private void startDrag(final int x, final int y) {
final View v = getChildAt(mDragPosition);
destroyDragImageView();
mDragImageView = createDragImageView(v, x, y);
v.setVisibility(View.INVISIBLE);
if (mDragAndDropListener != null) {
mDragAndDropListener.onDragItem(mDragPosition);
}
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if (mCurrentPosition == -1)
return i;
else if (i == childCount - 1)
return mCurrentPosition;
else if (i >= mCurrentPosition)
return i + 1;
return i;
}
private void onDrop() {
destroyDragImageView();
removeCallbacks(mDelayedOnDragRunnable);
View v = getChildAt(mDropPosition);
v.setVisibility(View.VISIBLE);
v.clearAnimation();
if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {
mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
}
mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
mDragAndDropStarted = false;
}
public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {
mScrollingStrategy = scrollingStrategy;
}
private void onDrag(final int x, final int y) {
if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {
removeCallbacks(mDelayedOnDragRunnable);
return;
}
final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);
if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {
removeCallbacks(mDelayedOnDragRunnable);
if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {
mDropPosition = tempDropPosition;
mDelayedOnDragRunnable = new Runnable() {
#Override
public void run() {
mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
performDragAndDropSwapping(mCurrentPosition, tempDropPosition);
final int nextDropPosition = pointToPosition(tempDropPosition, x, y);
if (nextDropPosition == AdapterView.INVALID_POSITION) {
mCurrentPosition = mDropPosition = tempDropPosition;
}
}
};
postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);
} else {
mDropPosition = mDragPosition;
}
}
if (mDragImageView != null) {
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
}
}
public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {
mOnTrackTouchEventsListener = onTrackTouchEventsListener;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mOnTrackTouchEventsListener != null) {
mOnTrackTouchEventsListener.trackTouchEvents(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (mDragAndDropListener != null && mDragAndDropStarted) {
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(true);
return launchDragAndDrop(event);
}
break;
default:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(event);
}
private boolean launchDragAndDrop(final MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);
if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
startDrag(x, y);
return true;
}
return false;
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {
final int x = (int) event.getX();
final int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
onDrag(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
onDrop();
resetLongClickTransition();
getParent().requestDisallowInterceptTouchEvent(false);
return false;
default:
}
return true;
}
return false;
}
}
Sample using this approach of a drag and drop is here

How to maintain multi layers of ImageViews and keep their aspect ratio based on the largest one?

Suppose I have multiple Images that I need to put one on top of the other, some might have some kind of animation appearing and some might even be draggable.
the largest one which usually takes the whole screen would be the bottom in the Z-coordinate (let's call it the backgroundImageView ), while all of the rest appear on top of it (and on top of others).
like so:
backgroundImageView
imageView1 , centered.
imageView2 , at 60%,60% of the top left corner
...
If I use a FrameLayout (which seems like the best solution), the backgroundImageView would have its size fit nicely, but how can I force the other layers resize themselves accordingly?
I think I need to somehow get where to put the other layers and how to set their sizes.
The easy way is to make sure all layers have the exact same size, but that could take a lot of memory and become very slow when animating or dragging views. It would be a huge waste if some of the layers have a very small content.
this is a class that displays an image with additional layers:
import java.util.ArrayList;
import java.util.Iterator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.widget.ImageView;
public class LayeredImageView extends ImageView {
private final static String TAG = "LayeredImageView";
private ArrayList<Layer> mLayers;
private Matrix mDrawMatrix;
private Resources mResources;
public LayeredImageView(Context context) {
super(context);
init();
}
public LayeredImageView(Context context, AttributeSet set) {
super(context, set);
init();
int[] attrs = {
android.R.attr.src
};
TypedArray a = context.obtainStyledAttributes(set, attrs);
TypedValue outValue = new TypedValue();
if (a.getValue(0, outValue)) {
setImageResource(outValue.resourceId);
}
a.recycle();
}
private void init() {
mLayers = new ArrayList<Layer>();
mDrawMatrix = new Matrix();
mResources = new LayeredImageViewResources();
}
#Override
protected boolean verifyDrawable(Drawable dr) {
for (int i = 0; i < mLayers.size(); i++) {
Layer layer = mLayers.get(i);
if (layer.drawable == dr) {
return true;
}
}
return super.verifyDrawable(dr);
}
#Override
public void invalidateDrawable(Drawable dr) {
if (verifyDrawable(dr)) {
invalidate();
} else {
super.invalidateDrawable(dr);
}
}
#Override
public Resources getResources() {
return mResources;
}
#Override
public void setImageBitmap(Bitmap bm) throws RuntimeException {
String detailMessage = "setImageBitmap not supported, use: setImageDrawable() " +
"or setImageResource()";
throw new RuntimeException(detailMessage);
}
#Override
public void setImageURI(Uri uri) throws RuntimeException {
String detailMessage = "setImageURI not supported, use: setImageDrawable() " +
"or setImageResource()";
throw new RuntimeException(detailMessage);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix matrix = getImageMatrix();
if (matrix != null) {
int numLayers = mLayers.size();
boolean pendingAnimations = false;
for (int i = 0; i < numLayers; i++) {
mDrawMatrix.set(matrix);
Layer layer = mLayers.get(i);
if (layer.matrix != null) {
mDrawMatrix.preConcat(layer.matrix);
}
if (layer.animation == null) {
draw(canvas, layer.drawable, mDrawMatrix, 255);
} else {
Animation a = layer.animation;
if (!a.isInitialized()) {
Rect bounds = layer.drawable.getBounds();
Drawable parentDrawable = getDrawable();
if (parentDrawable != null) {
Rect parentBounds = parentDrawable.getBounds();
a.initialize(bounds.width(), bounds.height(), parentBounds.width(), parentBounds.height());
} else {
a.initialize(bounds.width(), bounds.height(), 0, 0);
}
}
long currentTime = AnimationUtils.currentAnimationTimeMillis();
boolean running = a.getTransformation(currentTime, layer.transformation);
if (running) {
// animation is running: draw animation frame
Matrix animationFrameMatrix = layer.transformation.getMatrix();
mDrawMatrix.preConcat(animationFrameMatrix);
int alpha = (int) (255 * layer.transformation.getAlpha());
// Log.d(TAG, "onDraw ********** [" + i + "], alpha: " + alpha + ", matrix: " + animationFrameMatrix);
draw(canvas, layer.drawable, mDrawMatrix, alpha);
pendingAnimations = true;
} else {
// animation ended: set it to null
layer.animation = null;
draw(canvas, layer.drawable, mDrawMatrix, 255);
}
}
}
if (pendingAnimations) {
// invalidate if any pending animations
invalidate();
}
}
}
private void draw(Canvas canvas, Drawable drawable, Matrix matrix, int alpha) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.concat(matrix);
drawable.setAlpha(alpha);
drawable.draw(canvas);
canvas.restore();
}
public Layer addLayer(Drawable d, Matrix m) {
Layer layer = new Layer(d, m);
mLayers.add(layer);
invalidate();
return layer;
}
public Layer addLayer(Drawable d) {
return addLayer(d, null);
}
public Layer addLayer(int idx, Drawable d, Matrix m) {
Layer layer = new Layer(d, m);
mLayers.add(idx, layer);
invalidate();
return layer;
}
public Layer addLayer(int idx, Drawable d) {
return addLayer(idx, d, null);
}
public void removeLayer(Layer layer) {
layer.valid = false;
mLayers.remove(layer);
}
public void removeAllLayers() {
Iterator<Layer> iter = mLayers.iterator();
while (iter.hasNext()) {
LayeredImageView.Layer layer = iter.next();
layer.valid = false;
iter.remove();
}
invalidate();
}
public int getLayersSize() {
return mLayers.size();
}
public class Layer {
private Drawable drawable;
private Animation animation;
private Transformation transformation;
private Matrix matrix;
private boolean valid;
private Layer(Drawable d, Matrix m) {
drawable = d;
transformation = new Transformation();
matrix = m;
valid = true;
Rect bounds = d.getBounds();
if (bounds.isEmpty()) {
if (d instanceof BitmapDrawable) {
int right = d.getIntrinsicWidth();
int bottom = d.getIntrinsicHeight();
d.setBounds(0, 0, right, bottom);
} else {
String detailMessage = "drawable bounds are empty, use d.setBounds()";
throw new RuntimeException(detailMessage);
}
}
d.setCallback(LayeredImageView.this);
}
public void startLayerAnimation(Animation a) throws RuntimeException {
if (!valid) {
String detailMessage = "this layer has already been removed";
throw new RuntimeException(detailMessage);
}
transformation.clear();
animation = a;
if (a != null) {
a.start();
}
invalidate();
}
public void stopLayerAnimation(int idx) throws RuntimeException {
if (!valid) {
String detailMessage = "this layer has already been removed";
throw new RuntimeException(detailMessage);
}
if (animation != null) {
animation = null;
invalidate();
}
}
}
private class LayeredImageViewResources extends Resources {
public LayeredImageViewResources() {
super(getContext().getAssets(), new DisplayMetrics(), null);
}
#Override
public Drawable getDrawable(int id) throws NotFoundException {
Drawable d = super.getDrawable(id);
if (d instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) d;
bd.getBitmap().setDensity(DisplayMetrics.DENSITY_DEFAULT);
bd.setTargetDensity(DisplayMetrics.DENSITY_DEFAULT);
}
return d;
}
}
}
and how it can be used:
final LayeredImageView v = new LayeredImageView(this);
Resources res = v.getResources();
v.setImageResource(R.drawable.background);
Matrix m;
m = new Matrix();
m.preTranslate(81, 146); // pixels to offset
final Layer layer1 = v.addLayer(res.getDrawable(R.drawable.layer1), m);
m = new Matrix();
m.preTranslate(62, 63); // pixels to offset
final Layer layer0 = v.addLayer(0, res.getDrawable(R.drawable.layer0), m);
final AnimationDrawable ad = new AnimationDrawable();
ad.setOneShot(false);
Drawable frame1, frame2;
frame1 = res.getDrawable(R.drawable.layer0);
frame2 = res.getDrawable(R.drawable.layer1);
ad.addFrame(frame1, 3000);
ad.addFrame(frame2, 1000);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.setBounds(200, 20, 300, 120);
v.addLayer(1, ad);
v.post(new Runnable() {
#Override
public void run() {
ad.start();
}
});
int[] colors = {
0xeeffffff,
0xee0038a8,
0xeece1126,
};
GradientDrawable gd = new GradientDrawable(Orientation.TOP_BOTTOM, colors);
gd.setBounds(0, 0, 100, 129);
gd.setCornerRadius(20);
gd.setStroke(5, 0xaa666666);
final Matrix mm = new Matrix();
mm.preTranslate(200, 69); // pixels to offset
mm.preRotate(20, 50, 64.5f);
final Layer layer2 = v.addLayer(2, gd, mm);
final Animation as = AnimationUtils.loadAnimation(this, R.anim.anim_set);
final Runnable action1 = new Runnable() {
#Override
public void run() {
Animation a;
Interpolator i;
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
return (float) Math.sin(input * Math.PI);
}
};
as.setInterpolator(i);
layer0.startLayerAnimation(as);
a = new TranslateAnimation(0, 0, 0, 100);
a.setDuration(3000);
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
float output = (float) Math.sin(Math.pow(input, 2.5f) * 12 * Math.PI);
return (1-input) * output;
}
};
a.setInterpolator(i);
layer1.startLayerAnimation(a);
a = new AlphaAnimation(0, 1);
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
return (float) (1 - Math.sin(input * Math.PI));
}
};
a.setInterpolator(i);
a.setDuration(2000);
layer2.startLayerAnimation(a);
}
};
OnClickListener l1 = new OnClickListener() {
#Override
public void onClick(View view) {
action1.run();
}
};
v.setOnClickListener(l1);
v.postDelayed(action1, 2000);
// final float[] values = new float[9];
// final float[] pts = new float[2];
// final Matrix inverse = new Matrix();;
// OnTouchListener l = new OnTouchListener() {
// #Override
// public boolean onTouch(View view, MotionEvent event) {
// int action = event.getAction();
// if (action != MotionEvent.ACTION_UP) {
// if (inverse.isIdentity()) {
// v.getImageMatrix().invert(inverse);
// Log.d(TAG, "onTouch set inverse");
// }
// pts[0] = event.getX();
// pts[1] = event.getY();
// inverse.mapPoints(pts);
//
// mm.getValues(values);
// // gd's bounds are (0, 0, 100, 129);
// values[Matrix.MTRANS_X] = pts[0] - 100 / 2;
// values[Matrix.MTRANS_Y] = pts[1] - 129 / 2;
// mm.setValues(values);
// v.invalidate();
// }
// return false;
// }
// };
// v.setOnTouchListener(l);
setContentView(v);
anim_set.xml looks like:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true"
>
<rotate
android:fromDegrees="0"
android:toDegrees="30"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2500"
/>
<scale
android:fromXScale="1"
android:toXScale="1.8"
android:fromYScale="1"
android:toYScale="1.8"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2500"
/>
</set>
with the following images:
background.png:
layer0.png:
layer1.png:
the result is:
IMPORTANT in order to prevent resources from auto OS scaling when loading from different drawable-* folders you have to use Resources object obtained from LayeredImageView.getResources() method
have fun!
just extend ImageView and override its onDraw method in order to draw additional layers
this is a minimal varsion (enhanced version with animations is in the second answer):
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class LayeredImageView extends ImageView {
private final static String TAG = "LayeredImageView";
ArrayList<Bitmap> mLayers;
public LayeredImageView(Context context) {
super(context);
init();
}
public LayeredImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mLayers = new ArrayList<Bitmap>();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix matrix = getImageMatrix();
if (matrix != null) {
int numLayers = mLayers.size();
for (int i = 0; i < numLayers; i++) {
Bitmap b = mLayers.get(i);
canvas.drawBitmap(b, matrix, null);
}
}
}
public void addLayer(Bitmap b) {
mLayers.add(b);
invalidate();
}
public void addLayer(int idx, Bitmap b) {
mLayers.add(idx, b);
invalidate();
}
public void removeLayer(int idx) {
mLayers.remove(idx);
}
public void removeAllLayers() {
mLayers.clear();
invalidate();
}
public int getLayersSize() {
return mLayers.size();
}
}
and how its used in your Activity:
LayeredImageView v = new LayeredImageView(this);
v.setImageResource(R.drawable.background);
Resources res = getResources();
v.addLayer(BitmapFactory.decodeResource(res, R.drawable.layer0));
v.addLayer(0, BitmapFactory.decodeResource(res, R.drawable.layer1));
setContentView(v);
here you have 3 images:
background.png
layer0.png
layer1.png
and three above combined
and finally the captured screen from the emulator

Drag and Drop in GridView in Android

How can a drag and drop functionality be implemented in Android GridView. Can anyone please provide the best link for the same?
see PagedDragDropGrid
Above example has implemented a paged grid with drag'n'drop movable items using ViewGroup.
Note# It supports Android 2.2 (API 8) and above.
This is finest example i ever seen in android drag and drop android 2.2. And which version you have used?
You can find the google's documentation on drag and drop here and a third parties example here.
What you're going to want to do is set every view in your gridView to be clickable and set the onTouchListener. In your onTouch method you would then handle the appropriate actions for ACTION_DOWN (user pressed down on screen), ACTION_MOVE (user moves finger around ont he screen) and ACTION_UP (user lifts finger from the screen).
Try another approach by using WindowManager :
package com.example.cooldraganddrop;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`
private static final int ITEM_HOVER_DELAY = 450;
private int mDragPointX;
private int mDragPointY;
private int mDragOffsetX;
private int mDragOffsetY;
private int mDragPosition = AdapterView.INVALID_POSITION;
private int mDropPosition = AdapterView.INVALID_POSITION;
private int mCurrentPosition = AdapterView.INVALID_POSITION;
private Runnable mDelayedOnDragRunnable = null;
ScrollingStrategy mScrollingStrategy = null;
WindowManager mWindowManager = null;
WindowManager.LayoutParams mWindowParams = null;
private ImageView mDragImageView = null;
private boolean mDragAndDropStarted = false;
private DragAndDropListener mDragAndDropListener = null;
private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;
public static interface OnTrackTouchEventsListener {
void trackTouchEvents(final MotionEvent motionEvent);
};
public static interface DragAndDropListener {
void onDragItem(int from);
void onDraggingItem(int from, int to);
void onDropItem(int from, int to);
boolean isDragAndDropEnabled(int position);
}
public CoolDragAndDropGridView(Context context) {
super(context);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
private void initialize() {
setOnTouchListener(this);
setChildrenDrawingOrderEnabled(true);
}
public void startDragAndDrop() {
mDragAndDropStarted = true;
}
public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {
mDragAndDropListener = dragAndDropListener;
}
private void destroyDragImageView() {
if (mDragImageView != null) {
mWindowManager.removeView(mDragImageView);
BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
if (bitmapDrawable != null) {
final Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
mDragImageView.setImageDrawable(null);
mDragImageView = null;
}
}
private ImageView createDragImageView(final View v, final int x, final int y) {
v.destroyDrawingCache();
v.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());
mDragPointX = x - v.getLeft();
mDragPointY = y - v.getTop();
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.alpha = 0.7f;
mWindowParams.windowAnimations = 0;
ImageView iv = new ImageView(getContext());
iv.setBackgroundColor(Color.parseColor("#ff555555"));
iv.setImageBitmap(bm);
mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
mWindowManager.addView(iv, mWindowParams);
return iv;
}
private void startDrag(final int x, final int y) {
final View v = getChildAt(mDragPosition);
destroyDragImageView();
mDragImageView = createDragImageView(v, x, y);
v.setVisibility(View.INVISIBLE);
if (mDragAndDropListener != null) {
mDragAndDropListener.onDragItem(mDragPosition);
}
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if (mCurrentPosition == -1)
return i;
else if (i == childCount - 1)
return mCurrentPosition;
else if (i >= mCurrentPosition)
return i + 1;
return i;
}
private void onDrop() {
destroyDragImageView();
removeCallbacks(mDelayedOnDragRunnable);
View v = getChildAt(mDropPosition);
v.setVisibility(View.VISIBLE);
v.clearAnimation();
if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {
mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
}
mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
mDragAndDropStarted = false;
}
public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {
mScrollingStrategy = scrollingStrategy;
}
private void onDrag(final int x, final int y) {
if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {
removeCallbacks(mDelayedOnDragRunnable);
return;
}
final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);
if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {
removeCallbacks(mDelayedOnDragRunnable);
if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {
mDropPosition = tempDropPosition;
mDelayedOnDragRunnable = new Runnable() {
#Override
public void run() {
mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
performDragAndDropSwapping(mCurrentPosition, tempDropPosition);
final int nextDropPosition = pointToPosition(tempDropPosition, x, y);
if (nextDropPosition == AdapterView.INVALID_POSITION) {
mCurrentPosition = mDropPosition = tempDropPosition;
}
}
};
postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);
} else {
mDropPosition = mDragPosition;
}
}
if (mDragImageView != null) {
mWindowParams.x = x - mDragPointX + mDragOffsetX;
mWindowParams.y = y - mDragPointY + mDragOffsetY;
mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
}
}
public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {
mOnTrackTouchEventsListener = onTrackTouchEventsListener;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mOnTrackTouchEventsListener != null) {
mOnTrackTouchEventsListener.trackTouchEvents(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (mDragAndDropListener != null && mDragAndDropStarted) {
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(true);
return launchDragAndDrop(event);
}
break;
default:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragAndDropStarted = false;
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(event);
}
private boolean launchDragAndDrop(final MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);
if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
startDrag(x, y);
return true;
}
return false;
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {
final int x = (int) event.getX();
final int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mDragOffsetX = (int) (event.getRawX() - x);
mDragOffsetY = (int) (event.getRawY() - y);
onDrag(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
onDrop();
resetLongClickTransition();
getParent().requestDisallowInterceptTouchEvent(false);
return false;
default:
}
return true;
}
return false;
}
}
Sample using this approach of a drag and drop is here

Categories

Resources