I am trying to create an Android application that will erase parts of an image. I am trying to accomplish so by using a dragable object (image of eraser).
I have already implemented the features of dragging the eraser image to anywhere in the app and erasing a background image upon dragging your finger. Now I want to bridge the two features so that the background image erases only when the eraser image is being dragged. How can I accomplish this task?
Below is what I have done so far:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyCustomView myCustomView = new MyCustomView(MainActivity.this);
w1 = (ImageView) findViewById(R.id.wand1);
pl = (RelativeLayout) findViewById(R.id.coordAct);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);
rootLayout.addView(myCustomView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
myCustomView.setLayoutParams(layoutParams1w2);
w1.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
private final class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1){
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
// detach the child from parent
rootLayout.removeView(w1);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
w1.setLayoutParams(layoutParams1);
clicked1 = true;
}
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
break;
}
rootLayout.invalidate();
return true;
}
}
MyCustomView.java
public class MyCustomView extends View {
private Bitmap sourceBitmap;
private Canvas sourceCanvas = new Canvas();
private Paint destPaint = new Paint();
private Path destPath = new Path();
public MyCustomView(Context context) {
super(context);
//converting drawable resource file into bitmap
Bitmap rawBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.armissueserase);
//converting bitmap into mutable bitmap
sourceBitmap = Bitmap.createBitmap(rawBitmap.getWidth(), rawBitmap.getHeight(), Bitmap.Config.ARGB_8888);
sourceCanvas.setBitmap(sourceBitmap);
sourceCanvas.drawBitmap(rawBitmap, 0, 0, null);
destPaint.setAlpha(0);
destPaint.setAntiAlias(true);
destPaint.setStyle(Paint.Style.STROKE);
destPaint.setStrokeJoin(Paint.Join.ROUND);
destPaint.setStrokeCap(Paint.Cap.ROUND);
//change this value as per your need
destPaint.setStrokeWidth(50);
destPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
#Override
protected void onDraw(Canvas canvas) {
sourceCanvas.drawPath(destPath, destPaint);
canvas.drawBitmap(sourceBitmap, 0, 0, null);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float xPos = event.getX();
float yPos = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
destPath.moveTo(xPos, yPos);
break;
case MotionEvent.ACTION_MOVE:
destPath.lineTo(xPos, yPos);
break;
default:
return false;
}
invalidate();
return true;
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/coordAct"
android:background="#drawable/background"
tools:context="com.erasewithtouch.MainActivity">
<RelativeLayout
android:id="#+id/parLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"
android:background="#0000ff">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="28dp"
android:background="#BA9DF7"
android:gravity="bottom"
android:orientation="vertical">
<HorizontalScrollView
android:id="#+id/backgd"
android:layout_width="match_parent"
android:layout_height="100dp"
android:weightSum="1">
<LinearLayout
android:id="#+id/parentLL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="5">
<ImageView
android:id="#+id/wand1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/wand1" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
Any help is greatly appreciated. Thanks!
Related
I want to drag a button/view from center of a card view layout to its adjacent sides.and the view should not go out of the card view.
This is what i did so far
<android.support.v7.widget.CardView
android:layout_width="300dp"
android:layout_height="300dp"
app:cardCornerRadius="150dp"
app:cardElevation="0dp"
android:gravity="center"
app:cardBackgroundColor="#50001848"
android:layout_centerInParent="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:id="#+id/root">
<ImageView
android:id="#+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:src="#mipmap/ic_launcher_round"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
ImageView _view;
ViewGroup _root;
private int _xDelta;
private int _yDelta;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_root = findViewById(R.id.root);
_view=findViewById(R.id.image);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(300, 300);
layoutParams.leftMargin = 50;
layoutParams.topMargin = 50;
layoutParams.bottomMargin = 50;
layoutParams.rightMargin = 50;
_view.setLayoutParams(layoutParams);
_view.setOnTouchListener(this);
}
#Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -50;
layoutParams.bottomMargin = -50;
view.setLayoutParams(layoutParams);
break;
}
_root.invalidate();
return true;
}
}
When i drag the image goes out of the circle.i want the image stay inside the circle and get the boundary of the circle.Please help to achieve this.
Place a Relative layout inside the card view.
Then inside the relative layout you can do this as simple.
Im making a simple drawing app using canvas. The problem is when I set a background image (of a black board) for the canvas, it only occupies ~66% of the screen. See screenshot/link:
Canvas View
I want my canvas view to occupy the entire screen except the bottom part that RelativeLayout with id parLayout occupies.
What am I doing wrong in my code? Here is what I have:
MainActivity.java
public class MainActivity extends AppCompatActivity {
public static int wandToUse1;
public static int wandToUse2;
public static int wandToUse3;
private ViewGroup rootLayout;
private ViewGroup rlWand2;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private RelativeLayout wn2;
private RelativeLayout wn1;
ImageView w1;
ImageView w2;
boolean clicked1 = false;
boolean clicked2 = false;
RelativeLayout ll;
public static int X;
public static int Y;
CanvasView canvasView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.parLayout);
canvasView = new CanvasView(MainActivity.this);
rootLayout.addView(canvasView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
canvasView.setLayoutParams(layoutParams1w2);
ll = (RelativeLayout) findViewById(R.id.parLayout);
w1 = (ImageView) findViewById(R.id.wand1);
w2 = (ImageView) findViewById(R.id.wand2);
w1.setImageResource(wandToUse1);
w2.setImageResource(wandToUse2);
pl = (RelativeLayout) findViewById(R.id.coordAct);
wn1 = (RelativeLayout) findViewById(R.id.rlw1);
wn2 = (RelativeLayout) findViewById(R.id.rlw2);
w1.setOnTouchListener(new ChoiceTouchListener());
w2.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1) {
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
rootLayout.removeView(w1);
}
rlWand2 = (ViewGroup) w2.getParent();
if (rlWand2 != null) {
rlWand2.removeView(w2);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(250, 250);
wn2.addView(w2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
w1.setLayoutParams(layoutParams1);
w2.setLayoutParams(layoutParams1w2);
clicked1 = true;
clicked2 = false;
}
X = (int) event.getRawX();
Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
canvasView.dispatchTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
canvasView.dispatchTouchEvent(event);
break;
}
rootLayout.invalidate();
return true;
}
}
CanvasView.java
public class CanvasView extends View{
private Bitmap sourceBitmap;
private Canvas sourceCanvas = new Canvas();
private Paint destPaint = new Paint();
public static Path destPath = new Path();
Bitmap rawBitmap;
public int width;
public int height;
public CanvasView(Context context) {
super(context);
init(context);
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CanvasView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
//converting drawable resource file into bitmap
rawBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.blackboard);
rawBitmap = Bitmap.createScaledBitmap(rawBitmap, width, height, false);
Rect frameToDraw = new Rect(0, 0, width, height);
RectF whereToDraw = new RectF(0, 0, width, height);
//converting bitmap into mutable bitmap
sourceBitmap = Bitmap.createBitmap(rawBitmap.getWidth(), rawBitmap.getHeight(), Bitmap.Config.ARGB_8888);
sourceCanvas.setBitmap(sourceBitmap);
sourceCanvas.drawBitmap(rawBitmap, frameToDraw,whereToDraw, null);
destPaint.setAlpha(0);
destPaint.setAntiAlias(true);
destPaint.setStyle(Paint.Style.STROKE);
destPaint.setStrokeJoin(Paint.Join.ROUND);
destPaint.setStrokeCap(Paint.Cap.ROUND);
//change this value as per your need
destPaint.setStrokeWidth(50);
destPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
#Override
protected void onDraw(Canvas canvas)
{
sourceCanvas.drawPath(destPath, destPaint);
canvas.drawBitmap(sourceBitmap, 0, 0, null);
super.onDraw(canvas);
}
public void clearCanvas() {
destPath.reset();
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
destPath.moveTo(MainActivity.X, MainActivity.Y-360);
break;
case MotionEvent.ACTION_MOVE:
destPath.lineTo(MainActivity.X, MainActivity.Y-360);
break;
default:
return false;
}
invalidate();
return true;
}
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/coordAct"
tools:context="com.simplepaintapp.MainActivity">
<RelativeLayout
android:id="#+id/parLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"
android:background="#color/colorAccent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:background="#BA9DF7"
android:gravity="bottom"
android:orientation="vertical">
<LinearLayout
android:id="#+id/parentLL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="5">
<RelativeLayout
android:id="#+id/rlw1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginRight="0dp"
android:layout_weight="1"
android:background="#color/colorPrimary">
<ImageView
android:id="#+id/wand1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#mipmap/pen" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlw2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginRight="0dp"
android:layout_weight="1"
android:background="#color/colorPrimary">
<ImageView
android:id="#+id/wand2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/eraser" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
Thank You!
I got it! I was a bit tired yesterday and couldn't think.
Just fix this line in MainActivity.java
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
To
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight());
I am trying to create a simple paint app using canvas. The end product would be for the user to select a tool of choice (pen, marker, eraser, etc) and draw or erase accordingly anywhere the tool is dragged on the canvas.
As of now, I only have a pen and I am trying to draw a line wherever the pen is dragged in the canvas. However, I am finding this task challenging. I can drag the pen and I can draw lines, but I can't draw while I am dragging the pen. I am reaching out to the SO community to bridge these two features.
Below is what I have:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CanvasView canvasView = new CanvasView(MainActivity.this);
w1 = (ImageView) findViewById(R.id.wand1);
pl = (RelativeLayout) findViewById(R.id.coordAct);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);
rootLayout.addView(canvasView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
canvasView.setLayoutParams(layoutParams1w2);
w1.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1){
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
// detach the child from parent
rootLayout.removeView(w1);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
w1.setLayoutParams(layoutParams1);
clicked1 = true;
}
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
break;
}
rootLayout.invalidate();
return true;
}
}
CanvasView.java
public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public CanvasView(Context context) {
super(context);
this.context=context;
path=new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(50);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w,h,oldw,oldh);
bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
canvas=new Canvas(bitmap);
}
public void startTouch(float x, float y) {
path.moveTo(x, y);
mX = x;
mY = y;
}
public void moveTouch(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if(dx>=TOLERANCE || dy>= TOLERANCE) {
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX=x;
mY=y;
}
}
//To clear canvas
public void clearCanvas() {
path.reset();
invalidate();
}
public void upTouch() {
path.lineTo(mX,mY);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
startTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
default:
return false;
}
invalidate();
return true;
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/coordAct"
tools:context="com.simplepaintapp.MainActivity">
<RelativeLayout
android:id="#+id/parLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"
android:background="#0000ff">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="28dp"
android:background="#BA9DF7"
android:gravity="bottom"
android:orientation="vertical">
<HorizontalScrollView
android:id="#+id/backgd"
android:layout_width="match_parent"
android:layout_height="100dp"
android:weightSum="1">
<LinearLayout
android:id="#+id/parentLL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="5">
<ImageView
android:id="#+id/wand1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/pen" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
Current bug after implementing the dispatchTouchEvent() method inside onTouch()
An update to MainActivity and CanvasView is required. See the new source code below:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
private RelativeLayout pl;
private ImageView w1;
private boolean clicked1 = false;
CanvasView canvasView;
public static int X;
public static int Y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
canvasView = new CanvasView(MainActivity.this);
w1 = (ImageView) findViewById(R.id.wand1);
pl = (RelativeLayout) findViewById(R.id.coordAct);
RelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.coordAct);
rootLayout.addView(canvasView);
RelativeLayout.LayoutParams layoutParams1w2 = new RelativeLayout.LayoutParams(getScreenWidth(), getScreenHeight() / 2);
layoutParams1w2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
canvasView.setLayoutParams(layoutParams1w2);
w1.setOnTouchListener(new ChoiceTouchListener());
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
if (!clicked1){
rootLayout = (ViewGroup) w1.getParent();
if (rootLayout != null) {
// detach the child from parent
rootLayout.removeView(w1);
}
RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(300, 300);
pl.addView(w1);
w1.setLayoutParams(layoutParams1);
clicked1 = true;
}
X = (int) event.getRawX();
Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
canvasView.dispatchTouchEvent(event);
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
canvasView.dispatchTouchEvent(event);
break;
}
rootLayout.invalidate();
return true;
}
}
CanvasView.java:
public class CanvasView extends View{
Context context;
int width, height;
Bitmap bitmap;
Path path;
public Canvas canvas;
Paint paint;
float mX, mY;
static final float TOLERANCE=4;
public static float x;
public static float y;
public CanvasView(Context context) {
super(context);
this.context=context;
path=new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(50);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w,h,oldw,oldh);
bitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
canvas=new Canvas(bitmap);
}
public void startTouch(float x, float y) {
path.moveTo(x, y);
mX = x;
mY = y;
}
public void moveTouch(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if(dx>=TOLERANCE || dy>= TOLERANCE) {
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX=x;
mY=y;
}
}
//To clear canvas
public void clearCanvas() {
path.reset();
invalidate();
}
public void upTouch() {
path.lineTo(mX,mY);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
startTouch(MainActivity.X,MainActivity.Y-380);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(MainActivity.X,MainActivity.Y-380);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
default:
return false;
}
invalidate();
return true;
}
I have working on a project. where I need to drag the layout, I manage to move (drag) the layout but when I release the touch it is not coming at its original position.
Please anyone tell me what should I do in MotionEvent.ACTION_UP so that I can get layout back to its original position.
Following is my code.
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class HomeActivity extends Activity implements OnTouchListener {
RelativeLayout _view;
RelativeLayout _view1;
// TextView _view;
ViewGroup _root;
private int _xDelta;
RelativeLayout.LayoutParams lParams;
RelativeLayout.LayoutParams mainlParams;
private int _yDelta;
// private int X1, Y1, width;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_root = (ViewGroup) findViewById(R.id.root);
_view = (RelativeLayout) findViewById(R.id.relativeLayout);
_view.setOnTouchListener(this);
lParams = (RelativeLayout.LayoutParams) _view.getLayoutParams();
mainlParams = (RelativeLayout.LayoutParams) _view.getLayoutParams();
// _root.addView(_view1);
}
public boolean onTouch(View view, MotionEvent event) {
int X = (int) event.getRawX();
int Y = (int) event.getRawY();
RelativeLayout.LayoutParams layoutParams;
lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.e("", "inside ACTION_DOWN");
lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
Log.e("", "inside ACTION_UP");
if ((X - _xDelta) < -150) {
_root.removeView(_view);
} else {
view.setLayoutParams(mainlParams);
}
break;
case MotionEvent.ACTION_MOVE:
Log.e("", "inside ACTION_MOVE");
layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
break;
}
_root.invalidate();
return true;
}
}
NEW EDIT
here I show you a very simple (and by the way not very clean code) how to do what you want to do. I have a relativeLayout with a green LinearLayout inside:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/moving_layout"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00ff00"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
</RelativeLayout>
Then in Your MainActivity, set the topLayout, where the view You want to move is inside, to onTouchListener. Set originalX and originalY at ACTION_DOWN and moveX and moveY at ACTION_MOVE. When user release fingers, go back to original position:
public class MainActivity extends Activity implements OnTouchListener {
private LinearLayout mLinearLayout;
private RelativeLayout mRelativeLayout;
private RelativeLayout.LayoutParams params;
private float originalX = 0;
private float originalY = 0;
private float moveX = 0;
private float moveY = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLinearLayout = (LinearLayout) findViewById(R.id.moving_layout);
mRelativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
mRelativeLayout.setOnTouchListener(this);
int width = getMetrics(100);
int height = getMetrics(100);
params = new RelativeLayout.LayoutParams(width, height);
}
/**
* converts dp to px
*
* #param dp
* #return
*/
private int getMetrics(int dp) {
DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
return (int) ((dp * displayMetrics.density) + 0.5);
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case (MotionEvent.ACTION_DOWN):
originalX = event.getX(); //set X start position
originalY = event.getY();//set Y start position
moveX = event.getX();//first move x
moveY = event.getY();//first move y
break;
case (MotionEvent.ACTION_MOVE):
moveX = event.getX();//set move x
moveY = event.getY();//set move y
//set LayoutParams to mLinearLayout
params.leftMargin = (int) moveX;
params.topMargin = (int) moveY;
mLinearLayout.setLayoutParams(params);
break;
case (MotionEvent.ACTION_UP):
//set mLinearLayout back to original position
params.leftMargin = (int) originalX;
params.topMargin = (int) originalY;
mLinearLayout.setLayoutParams(params);
break;
}
return true;
}
}
DonĀ“t wonder about the getMetrics() Method, this is because setting same width and height to mLinearLayout like defined in xml. In xml, you set this values as dp, at LayoutParams, it is px. But this is not relevant for Your question.
What I am doin here is, set original X and Y at ACTION_DOWN and get back to this at ACTION_UP. So, everytime the user press down again, these values will be "renewed", the layout will going back to the last points of ACTION_DOWN if fingers will release. This should give You an idea how to handle your problem.
I am trying to enable pinch-zooming on an imageswitcher. I am stuck right now in how to declare the imageview in the ontouch method. I realize that the ImageView i = (Imageview) v is incorrect, I just dont know what to switch it to to declare the imageswitcher imageview in the ontouch...
Here is my java and xml. Thank you for your help!
public class ImageSwitch1 extends Activity implements
AdapterView.OnItemSelectedListener, ViewSwitcher.ViewFactory, OnTouchListener {
Matrix matrix = new Matrix();
Matrix eventMatrix = new Matrix();
final static int NONE = 0;
final static int DRAG = 1;
final static int ZOOM = 2;
int touchState = NONE;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.imageswitcher);
mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
mSwitcher.setFactory(this);
mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_in));
mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_out));
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this));
g.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView parent, View v, int position, long id) {
final TextView tv = (TextView)findViewById(R.id.SwitcherText);
mSwitcher.setImageResource(mImageIds[position]);
tv.setText(mText[position]);
}
public void onNothingSelected(AdapterView parent) {
}
public View makeView() {
ImageView i = new ImageView(this);
i.setScaleType(ScaleType.MATRIX);
i.setBackgroundColor(0xFF000000);
i.setScaleType(ImageView.ScaleType.FIT_CENTER);
i.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
i.setOnTouchListener(this);
return i;
}
final static float MIN_DIST = 50;
static float eventDistance = 0;
static float centerX =0, centerY = 0;
public boolean onTouch(View v, MotionEvent event) {
ImageView i = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//primary touch event starts: remember touch down location
touchState = DRAG;
centerX = event.getX(0);
centerY = event.getY(0);
eventMatrix.set(matrix);
break;
case MotionEvent.ACTION_POINTER_DOWN:
//secondary touch event starts: remember distance and center
eventDistance = calcDistance(event);
calcMidpoint(centerX, centerY, event);
if (eventDistance > MIN_DIST) {
eventMatrix.set(matrix);
touchState = ZOOM;
}
break;
case MotionEvent.ACTION_MOVE:
if (touchState == DRAG) {
//single finger drag, translate accordingly
matrix.set(eventMatrix);
matrix.setTranslate(event.getX(0) - centerX,
event.getY(0) - centerY);
} else if (touchState == ZOOM) {
//multi-finger zoom, scale accordingly around center
float dist = calcDistance(event);
if (dist > MIN_DIST) {
matrix.set(eventMatrix);
float scale = dist / eventDistance;
matrix.postScale(scale, scale, centerX, centerY);
}
}
// Perform the transformation
i.setImageMatrix(matrix);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
touchState = NONE;
break;
}
return true;
}
private float calcDistance(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void calcMidpoint(float centerX, float centerY,
MotionEvent event) {
centerX = (event.getX(0) + event.getX(1))/2;
centerY = (event.getY(0) + event.getY(1))/2;
}
private ImageSwitcher mSwitcher;
public class ImageAdapter extends BaseAdapter {
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageResource(mThumbIds[position]);
i.setAdjustViewBounds(true);
i.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
i.setBackgroundResource(R.drawable.picture_frame);
return i;
}
private Context mContext;
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Rellayout1"
android:layout_width="match_parent" android:layout_height="match_parent" android:isScrollContainer="true">
<RelativeLayout android:id="#+id/RelativeLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:isScrollContainer="true" android:layout_marginBottom="120dp">
<ImageSwitcher android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="#+id/switcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"
>
</ImageSwitcher>
<Gallery android:spacing="16dp" android:layout_height="80dp" android:id="#+id/gallery" android:unselectedAlpha="0.5" android:background="#55000000" android:gravity="center_vertical" android:layout_width="match_parent" android:minHeight="20px"></Gallery>
</RelativeLayout>
<ScrollView
android:id="#+id/ScrollViewSwitcher"
android:layout_width="fill_parent" android:scrollbarAlwaysDrawVerticalTrack="true" android:isScrollContainer="true" android:layout_alignParentBottom="true" android:layout_height="120dp">
<TextView android:scrollbarAlwaysDrawVerticalTrack="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="#+id/SwitcherText" android:textSize="18dp"></TextView>
</ScrollView>
</RelativeLayout>
I solved this problem changing this line:
ImageView i = (ImageView) v;
By
ImageView i = mSwitcher;
But can't use matrix, imageSwitcher don't use matrix or i do not know how it's done.
I hope help you with this.