how to draw a Bitmap and move it in java Android? - java

I have spent a good month trying to do all of this together.
Draw Bitmap to screen
On create move Bitmap down at a constant rate
Stop the Bimap when it reaches the bottom
Allow the Bitmap to be clicked on while it moves (a.k.a. not translation animation)
Thanks for you for helping put this all together in advance.
Here is my attempt:
package com.example.animating;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class FirstView extends View {
private int screenW;
private int screenH;
private float drawScaleW;
private float drawScaleH;
int moveRate = 10, dot1y, dot1x;
private Context myContext;
private Bitmap dot;
private boolean dotSinking = true, gameOver = false;
public FirstView(Context context) {
super(context);
myContext = context;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
dot = BitmapFactory.decodeResource(myContext.getResources(), R.drawable.dot);
screenW = w;
screenH = h;
drawScaleW = (float) screenW / 800;
drawScaleH = (float) screenH / 600;
dot1y = (int) (475*drawScaleH);
dot1x = (int) (55*drawScaleW);
}
public void run() {
if (!gameOver) {
animateDot();
}
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
Paint redPaint = new Paint();
redPaint.setColor(Color.RED);
canvas.drawBitmap(dot, dot1x, dot1y, null);
}
private void animateDot(){
if (dotSinking) {
dot1y -= moveRate;
}
}
}

To answer first part of your question
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/button1"
/>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Button" />
</RelativeLayout>
MainActivity class
public class MainActivity extends Activity
{
FirstView dv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new FirstView(this);
setContentView(R.layout.activity_main);
final Button b= (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener()
{
public void onClick(View v) {
// TODO Auto-generated method stub
LinearLayout rl= (LinearLayout ) findViewById(R.id.textView1);
rl.addView(dv);
b.setVisibility(View.INVISIBLE);
}
});
}
public class FirstView extends View {
private int screenW;
private int screenH;
private float drawScaleW;
private float drawScaleH;
int moveRate = 10, dot1y, dot1x;
private Context myContext;
private Bitmap dot;
private boolean dotSinking = true, gameOver = false;
public FirstView(Context context) {
super(context);
myContext = context;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
dot = BitmapFactory.decodeResource(myContext.getResources(), R.drawable.ic_launcher);
screenW = w;
screenH = h;
drawScaleW = (float) screenW / 800;
drawScaleH = (float) screenH / 600;
dot1y = 0+dot.getHeight();
dot1x = w/2-(dot.getWidth()/2);
}
public void run() {
if (!gameOver) {
animateDot();
invalidate();
}
}
#Override
protected void onDraw(Canvas canvas) {
Paint redPaint = new Paint();
redPaint.setColor(Color.RED);
canvas.drawBitmap(dot, dot1x, dot1y, null);
run();
}
private void animateDot(){
if (dotSinking) {
if(dot1y<screenH-dot.getHeight())
dot1y += moveRate;
}
}
}
I have a button at the bottom of the screen. When clicked (button becomes invisible) the image moves from the top to the height of the layout. When it reaches the layout height it stops.
I don't know how to add a click listener for the image moving.
Answered first part of the question. Modify the above according to your needs.

you should use the invalidate() method inside your onDraw() to make it redraw your bitmap's new position. and to make it stop when i reaches the bottom use the setbounds method for your bitmap inside an if sentence telling the bitmap that when the distance with the screec is 0 make it stop. you should set an onclicklistener to your bitmap.to.make it.clickable . hope this helps you!

Related

How to convert a canvas drawing to an image then Drag it around screen?

I'm trying to draw on a canvas then onClick change it to bitmap image then I would like to make it draggable. I can draw on canvas successfully
but how do I convert this drawing to an image then make it draggable? I don't mind If it's possible to drag the drawing without converting to an image. Can someone please help.
public class MainActivity extends AppCompatActivity implements ColorPickerDialog.OnColorChangedListener {
protected DrawView canvasView;
private ImageButton blackCircle;
private Button pens,select;
private Paint mPaint;
Bitmap viewCapture = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPaint = new Paint();
canvasView = (DrawView) findViewById(R.id.canvas_view);//The drawing mechanism
colorChanged(mPaint.getColor());
blackCircle = (ImageButton) findViewById(R.id.black_circle);
blackCircle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
canvasView.setPathColor(Color.BLACK));
blackCircle.setPressed(true);
}
});
select = (Button) findViewById(R.id.ic_select);
select.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
canvasView.setVisibility(View.VISIBLE);
canvasView.setPathColor(0);
//Drag the drawn image
setContentView(R.layout.activity_main);
relativeLayout = (RelativeLayout) findViewById(R.id.main);
drawingView = new DrawingView(MainActivity.this);
relativeLayout.addView(drawingView);
//Create a bitmap image of current drawing
canvasView.setDrawingCacheEnabled(true);
viewCapture = Bitmap.createBitmap(canvasView.getDrawingCache());
canvasView.setDrawingCacheEnabled(false);
}
});
}// End of Create();
private void clearCanvas(View v) {
canvasView.clear();
}
#Override
public void colorChanged(int color) {
mPaint.setColor(color);
canvasView.setPathColor(mPaint.getColor());
}
/************** OnTouch ***************/
class DrawingView extends View{
float x,y;
public DrawingView(Context context){
super(context);
viewCapture = BitmapFactory.decodeResource(context.getResources(), R.id.main);
}
public boolean onTouchEvent(MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
x =(int)event.getX();
y =(int)event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
x =(int)event.getX();
y =(int)event.getY();
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.CYAN);
canvas.drawBitmap(viewCapture, x, y, paint);
}
}
}//End of Class
public class DrawView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;
public DrawView(Context context) {
super(context);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupDrawing();
}
private void setupDrawing() {
paths = new SparseArray<>();
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(9);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (int i=0; i<paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), drawPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int id = event.getPointerId(index);
Path path;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
path = new Path();
path.moveTo(event.getX(index), event.getY(index));
paths.put(id, path);
break;
case MotionEvent.ACTION_MOVE:
for (int i=0; i<event.getPointerCount(); i++) {
id = event.getPointerId(i);
path = paths.get(id);
if (path != null) path.lineTo(event.getX(i), event.getY(i));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(id);
if (path != null) {
drawCanvas.drawPath(path, drawPaint);
paths.remove(id);
}
break;
default:
return false;
}
invalidate();
return true;
}
public void setPathColor(int color) {
drawPaint.setColor(color);
}
public void clear() {
canvasBitmap.eraseColor(Color.TRANSPARENT);
paths.clear();
invalidate();
System.gc();
}
}
For the next steps I assume you'd like to let the users drag the picture which they just created with the DrawView. So I'd introduce another View which can display the bitmap and set its position and dimensions exactly like those of the DrawView. (The best way to achieve this depends on the type of ViewGroup you are using)
Create a bitmap from the canvas as shown in converting a canvas into bitmap image in android
Set the bitmap as the new View's background with setBackground(Drawable), toggle the visibility of both Views as needed.
To make the new View draggable, use a View.OnTouchListener and change the position according to the MotionEvents
Another option: just drag the DrawView by using a flag to indicate whether the users can drag it or draw on it. You override onTouchEvent() already, now check the flag first and if it is set to "drag" then evaluate the delta between two MOVEs and adjust the position accordingly.

Cannot draw a circle with loading of the fragment

I am trying to draw circles in the canvas. Currently I can do it on button click, but I also need to do the same when the Fragment is loaded. Below is my Fragment code.
public class StepTwentyOneFragment extends Fragment {
private CanvasView customCanvas;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.step21_fragment, container, false);
customCanvas=(CanvasView)v.findViewById(R.id.signature_canvas);
final Button button1=(Button)v.findViewById(R.id.step18button1);
float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
customCanvas.drawCircle(radius);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v.getId()==R.id.step18button1){
float radius=(customCanvas.getCanvasWidth()/2) - ((customCanvas.getCanvasWidth()/2)/100)*60;
customCanvas.drawCircle(radius);
Log.d("An_Width", "" + customCanvas.getCanvasWidth());
Log.d("An_Height" ,""+ customCanvas.getCanvasHeight());
v.setBackgroundResource(R.drawable.button_border_5);
button1.setTextColor(Color.WHITE);;
}
}
});
return v;
}
public static StepTwentyOneFragment newInstance() {
StepTwentyOneFragment f = new StepTwentyOneFragment();
Bundle b = new Bundle();
f.setArguments(b);
return f;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
Activity a = getActivity();
if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
Below is my Canvas code
public class CanvasView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
private int canvasHeight, canvasWidth;
private float radius;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
mPath = new Path();
mPaint = new Paint();
mPaint.setStrokeWidth(3);
mPaint.setColor(Color.CYAN);
}
// override onDraw
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas=canvas;
Drawable d = getResources().getDrawable(R.drawable.circle_1);
canvasHeight= canvas.getHeight();
canvasWidth= canvas.getWidth();
Log.d("Height - "," / "+canvas.getHeight());
Log.d("Width - "," / "+canvas.getWidth());
// DisplayMetrics displaymetrics = new DisplayMetrics();
// ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
// int height = displaymetrics.heightPixels;
// int width = displaymetrics.widthPixels;
float h=canvasHeight/2;
float w=canvasWidth/2;
d.setBounds(0, 0, canvasWidth, canvasHeight);
d.draw(canvas);
canvas.drawCircle(w, h, radius, mPaint);
}
public void clear2(){
radius=0;
//important. Refreshes the view by calling onDraw function
invalidate();
}
public void drawCircle(float radius1) {
radius=radius1;
//important. Refreshes the view by calling onDraw function
invalidate();
}
public int getCanvasHeight()
{
return canvasHeight;
}
public int getCanvasWidth()
{
return canvasWidth;
}
}
Now my problem is , cannot draw a circle with loading of the fragment . It means the circle cannot draw without button action . But I want to do it when the fragment is loading .
Have any ideas ?
Thank you.

Trying to fix my code but I keep failing :(

I've got this code that makes the image turn into a circle using a ListView. But as seen in the image, it dies when it goes to the end of the photo (the last few pixels are carried on when there not supposed to).
I don't want the photo to take up the whole page, just the size of the photo. Here's the code and XML:
Stream item 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="wrap_content" >
</RelativeLayout>
activity stream xml:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:divider="#null"
android:dividerHeight="0px"
android:drawSelectorOnTop="true"
tools:context=".StreamActivity" />
main code:
public class StreamActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream);
StreamAdapter adapter = new StreamAdapter(this);
((ListView) findViewById(R.id.main_list)).setAdapter(adapter);
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
}
class StreamItem {
final Bitmap mBitmap;
StreamItem(Context c, int resid, String line1, String line2) {
mBitmap = BitmapFactory.decodeResource(c.getResources(), resid);
}
}
class StreamDrawable extends Drawable {
private static final boolean USE_VIGNETTE = true;
private final float mCornerRadius;
private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;
StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
mCornerRadius = cornerRadius;
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
if (USE_VIGNETTE) {
RadialGradient vignette = new RadialGradient(
mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
Shader.TileMode.CLAMP);
Matrix oval = new Matrix();
oval.setScale(1.0f, 0.7f);
vignette.setLocalMatrix(oval);
mPaint.setShader(
new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
}
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
class StreamAdapter extends ArrayAdapter<StreamItem> {
private static final int CORNER_RADIUS =100; // dips
private static final int MARGIN = 1; // dips
private final int mCornerRadius;
private final int mMargin;
private final LayoutInflater mInflater;
public StreamAdapter(Context context) {
super(context, 0);
final float density = context.getResources().getDisplayMetrics().density;
mCornerRadius = (int) (CORNER_RADIUS * density + 0.5f);
mMargin = (int) (MARGIN * density + 0.5f);
mInflater = LayoutInflater.from(getContext());
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewGroup view = null;
if (convertView == null) {
view = (ViewGroup) mInflater.inflate(R.layout.stream_item, parent, false);
} else {
view = (ViewGroup) convertView;
}
StreamItem item = getItem(position);
StreamDrawable d = new StreamDrawable(item.mBitmap, mCornerRadius, mMargin);
view.setBackgroundDrawable(d);
int w = item.mBitmap.getWidth();
int h = item.mBitmap.getHeight();
float ratio = w / (float) h;
LayoutParams lp = view.getLayoutParams();
lp.width = getContext().getResources().getDisplayMetrics().widthPixels;
lp.height = (int) (lp.width / ratio);
return view;
}
}
}

onSizeChanged returns width, but not height

I need to get height and width of my View and I have followed examples given here with subclassing View and using onSizeChanged(...).
But what is very strange is that onSizeChanged gives me the correct width, but height is always 0. Here's my subclass:
public class MyView extends TextView {
int xMax=0; int yMax=0;Context c;
public MyView(Context context) {
super(context);
this.c=context;
}
#Override
public void onSizeChanged(int w, int h, int oldW, int oldH) {
xMax = w;
yMax = h;
My Activity class:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView dummyView = new MyView(this);
LinearLayout ll = (LinearLayout) findViewById(R.id.mainmtc);
ll.addView(dummyView);
and my XML Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainmtc" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1"
androiad:orientation="vertical">
I think it's normal, there is no content in your view so the height is 0.
Try to add some text in your custom textview and height will change
TextView dummyView = new MyView(this);
dummyView.setText("Hello");
Device screen dimensions : http://developer.android.com/reference/android/util/DisplayMetrics.html

Android drag around many views on a superview

I am starting to think that short of OpenGL I can't drag around a simple view. Seriously, I have read through 10-15 tutorials for dragging views, and EVERY tutorial shows you how to drag a drawable WITHIN a view, or drag an image INSIDE of an imageview (by matrix transformations). But NONE of the tutorials tell you how you can drag around a simple view in a superview. Its really that simple. I have a superview, I add lets say 10 subviews. Whatever subview my finger is touching drags around. I made an app for iOS http://www.facebook.com/MakeASnowman (hits the app store any day) and am trying to build it for Android. But there is no easy way to do things that are so simple in iOS (two finger rotate, drag around views, etc). This is what I want: I have a custom view that draws an image to its canvas. I then instantiate one or more of those custom views onto a "superview". I can drag/manipulate those views (meaning im not translating the drawables within those views, but the actual views themselves).
Here is my code that has the right manipulations, except it performs them of the drawable within the view:
package com.spentaklabs.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class MAView extends View
{
Drawable image;
private String imgName;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public MAView(Context context)
{
super(context);
}
public MAView(Context context,String imgName)
{
this(context);
this.imgName = imgName;
image = context.getResources().getDrawable(R.drawable.hatshairears0);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
public MAView(Context context, AttributeSet attrs, int defStyle)
{
super(context,attrs,defStyle);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.save();
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
image.draw(canvas);
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
{
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE:
{
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP:
{
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL:
{
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP:
{
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId)
{
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}
Here is some code that would let you drag a View anywhere you want on the screen...
package com.matthieu;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.FrameLayout.LayoutParams;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.util.ArrayList;
import java.util.Arrays;
public class DragActivity extends Activity implements View.OnTouchListener, AdapterView.OnItemLongClickListener
{
private static final String TAG="DragActivity";
private static final int NOT_DRAGGING = 0;
private static final int DRAGGING = 1;
private int state=NOT_DRAGGING;
private ImageView draggable =null;
private int dragged_position;
float current_x, current_y;
int current_icon = R.drawable.notepad;
private ArrayList<String> names = new ArrayList<String>(Arrays.asList("Matt", "Xiaohui", "Yong", "Hunt", "Andy", "Ivy", "Guanglong", "Zeyan", "Yanxia",
"Chris", "Mark", "Matthieu"));
private ArrayList<Integer> icons = new ArrayList<Integer>(Arrays.asList( R.drawable.glasses, R.drawable.monkey, R.drawable.normal, R.drawable.smile, R.drawable.wink));
private ArrayList<Integer> matching;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupListContent();
ListView list = (ListView) findViewById(R.id.main_list);
list.setAdapter(new DragListAdapter());
list.setOnItemLongClickListener(this);
list.setOnTouchListener(this);
ImageView image = (ImageView) findViewById(R.id.main_image);
image.setImageResource(current_icon);
}
private void setupListContent() {
matching = new ArrayList<Integer>();
for (int i=0; i<names.size(); i++) {
matching.add((int) (icons.size() * Math.random()));
}
}
#SuppressWarnings("unchecked")
private class DragListAdapter extends ArrayAdapter {
public DragListAdapter() {
super(DragActivity.this, R.layout.list_item, names);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.list_item, parent, false);
}
row.setDrawingCacheEnabled(true);
TextView name = (TextView) row.findViewById(R.id.item_text);
ImageView icon = (ImageView) row.findViewById(R.id.item_icon);
name.setText(names.get(position));
icon.setImageResource(icons.get(matching.get(position)));
return row;
}
}
private boolean checkOnDropIcon(MotionEvent me) {
ImageView drop_icon = (ImageView) findViewById(R.id.main_image);
Rect icon_rect = new Rect();
drop_icon.getGlobalVisibleRect(icon_rect);
Log.d(TAG, "icon at " + icon_rect.left + "<- ->" + icon_rect.right + ", " +
icon_rect.top + " ^ v" + icon_rect.bottom);
if ((me.getRawX()<icon_rect.left) || (me.getRawX()>icon_rect.right) ||
(me.getRawY()<icon_rect.top) || (me.getRawY()>icon_rect.bottom)) {
return false;
}
else {
return true;
}
}
private void checkOnDrop(MotionEvent me) {
boolean onDropIcon = checkOnDropIcon(me);
ImageView image = (ImageView) findViewById(R.id.main_image);
if ((onDropIcon) && (current_icon==R.drawable.notepad)) {
current_icon = R.drawable.exit;
image.setImageResource(current_icon);
image.invalidate();
return;
}
if ((!onDropIcon) && (current_icon==R.drawable.exit)) {
current_icon = R.drawable.notepad;
image.setImageResource(current_icon);
image.invalidate();
return;
}
}
public boolean onTouch(View view, MotionEvent me) {
if (state == NOT_DRAGGING) {
// get the position of the touch so we know where to place the dragging item if it is a long press
current_x = me.getRawX();
current_y = me.getRawY();
return false;
}
else {
FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space);
if (me.getAction()==MotionEvent.ACTION_UP) {
frame.removeAllViews();
draggable=null;
frame.setVisibility(View.GONE);
state=NOT_DRAGGING;
// check if we dropped a name
if (checkOnDropIcon(me)) {
names.remove(dragged_position);
matching.remove(dragged_position);
ListView list = (ListView) findViewById(R.id.main_list);
DragListAdapter adapter = (DragListAdapter) list.getAdapter();
adapter.notifyDataSetChanged();
}
// restore the icon
ImageView image = (ImageView) findViewById(R.id.main_image);
current_icon = R.drawable.notepad;
image.setImageResource(current_icon);
image.invalidate();
}
if (me.getAction()==MotionEvent.ACTION_MOVE) {
int frame_position[] = new int[2];
frame.getLocationOnScreen(frame_position);
draggable.setPadding(
(int) me.getRawX()-frame_position[0]-(draggable.getDrawable().getIntrinsicWidth()/2),
(int) me.getRawY()-frame_position[1]-(draggable.getDrawable().getIntrinsicHeight()/2),
0, 0);
draggable.invalidate();
checkOnDrop(me);
}
return true;
}
}
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
if (state == DRAGGING) {
Log.d(TAG, "already have an object moving... ?");
return false;
}
FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space);
int frame_position[] = new int[2];
frame.getLocationOnScreen(frame_position);
// setup everything for dragging
state = DRAGGING;
dragged_position = i;
draggable = new ImageView(this);
Bitmap bm = view.getDrawingCache();
draggable.setImageBitmap(bm);
draggable.setAlpha(150);
draggable.setScaleType(ImageView.ScaleType.CENTER);
draggable.setDrawingCacheEnabled(true);
draggable.setPadding((int) current_x-frame_position[0]-(bm.getWidth()/2), (int) current_y-frame_position[1]-(bm.getHeight()/2), 0, 0);
frame.setVisibility(View.VISIBLE);
frame.addView(draggable, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
return true;
}
}
Here is the main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="#+id/main_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<ImageView
android:id="#+id/main_image"
android:layout_width="fill_parent"
android:layout_height="32sp"
/>
</LinearLayout>
<FrameLayout
android:id="#+id/drag_space"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"/>
</FrameLayout>
And the list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/item_icon"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_margin="3sp"/>
<TextView
android:id="#+id/item_text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
Hope that helps.

Categories