I have a setup in which I have some ImageViews around a center, and when the user clicks a Button, I want the Views to rotate around the center view, in an elliptical way.
What I have at current time is an elliptical movement, but the view is rotating in a weird axis, not on the center axis, as required.
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.didasko.calculus.maca.TelaAtomo"
>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/maca_cinza"
android:background="#null"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tela_atomo_eletron_0"
android:src="#drawable/eletron_nao_completado"
android:background="#null"
android:layout_marginRight="46dp"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_marginBottom="78dp"
android:layout_above="#+id/tela_atomo_maca_central"/>
</RelativeLayout>
tela_atomo_maca_central is the center element
tela_atomo_eletron_0 is the view I want to move elliptically
final ImageButton eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = 46 * Math.cos(i);
double y = 78 * Math.sin(i);
Ponto p = new Ponto(x,y);
pontos.add(p);
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
eletron.postDelayed(eletronRunnable,100);
}
private class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
I'm probably making logical mistakes, because I can make it move elliptically, just not where I want.
How can I make the Image move elliptically around the center?
Based on your existing code I made a sample project and here is what I acheived -
Here is the modified code -
public class ActivityTest extends AppCompatActivity {
ImageButton eletron,center;
ArrayList<Ponto> pontos = new ArrayList<>();
int contagem = 0;
DemoRelativeLayout rel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.so_demo);
eletron = (ImageButton) findViewById(R.id.tela_atomo_eletron_0);
center = (ImageButton) findViewById(R.id.tela_atomo_maca_central);
rel = (DemoRelativeLayout)findViewById(R.id.demo);
//Getting all points in the ellipse
for(int i=0;i<360;i++) {
double x = (200 * Math.cos(i));
double y = (400 * Math.sin(i));
Ponto p = new Ponto(x,y);
pontos.add(p);
}
eletron.postDelayed(eletronRunnable,2000);
}
#Override
protected void onStart() {
super.onStart();
rel.drawCircle(pontos,center.getX() + center.getWidth()/2,center.getY() + center.getHeight()/2);
rel.invalidate();
}
Runnable eletronRunnable = new Runnable() {
#Override
public void run() {
if (contagem < 360) {
Ponto p = pontos.get(contagem);
contagem++;
/*RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) eletron.getLayoutParams();
params.rightMargin = (int)p.getX();
params.bottomMargin = (int)p.getY();
eletron.setLayoutParams(params);*/
eletron.setTranslationX((float) p.getX() + (eletron.getWidth()/2 + center.getWidth()/2));
eletron.setTranslationY((float)p.getY() + (eletron.getHeight()/2 + center.getHeight()/2));
eletron.postDelayed(this,100);
}else {
contagem = 0;
eletron.postDelayed(this,100);
}
}
};
public class Ponto {
private double x,y;
public Ponto(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
}
I have also changed the xml file -
<com.wandertails.stackovrflw.DemoRelativeLayout
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"
android:padding="10dp"
android:background="#ffffff"
android:id="#+id/demo"
>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_maca_central"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#444444"
android:background="#null"/>
<ImageButton
android:layout_width="40dp"
android:layout_height="40dp"
android:id="#+id/tela_atomo_eletron_0"
android:src="#880080"
android:background="#null"
android:layout_toLeftOf="#+id/tela_atomo_maca_central"
android:layout_above="#+id/tela_atomo_maca_central"/>
</com.wandertails.stackovrflw.DemoRelativeLayout>
Finally the DemoRelativeLayout if you want to draw the elliptical path -
public class DemoRelativeLayout extends RelativeLayout
{
ArrayList<ActivityTest.Ponto> pontos;
float cntrX,cntrY;
public DemoRelativeLayout(Context context) {
super(context);
}
public DemoRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DemoRelativeLayout(Context context, AttributeSet attrs, intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(pontos != null){
Paint p = new Paint();
p.setColor(Color.RED);
for (ActivityTest.Ponto pt : pontos){
float x = (float)pt.getX() + cntrX;
float y = (float)pt.getY() + cntrY;
canvas.drawCircle(x,y,5,p);
}
}
}
public void drawCircle(ArrayList<ActivityTest.Ponto> pp,float x,float y){
cntrX = x;
cntrY = y;
pontos = pp;
}
}
I hope this is all you want..
Related
I am new to learning android, and I am writing a program to show a point and its position(coordination) on the screen.
I use TextView to show the coordinates, and using CustomView to draw the point out.
Here is my 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:id="#+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/tv_pointX"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="X : "
android:textSize="24sp" />
<TextView
android:id="#+id/tv_pointY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:text="Y : "
android:textSize="24sp" />
</LinearLayout>
<com.example.pointnsendmsgtest3.svPaintCircle
android:id="#+id/TouchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp">
</com.example.pointnsendmsgtest3.svPaintCircle>
</LinearLayout>
</RelativeLayout>
And my main activity of the code. I am just wondering that how can I display all the views in one screen.
There is only one view can be displayed on the screen, base on the last setContentView command shows in my script to the compiler.
public class MainActivity extends Activity{
private TextView tv_pointx;
private TextView tv_pointy;
private LinearLayout panel_touch;
private svPaintCircle m_view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
m_view = new svPaintCircle(this);
m_view.setOnTouchListener(new MyListener());
setContentView(m_view);
setContentView(R.layout.activity_main);
}
public class MyListener implements View.OnTouchListener {
public boolean onTouch(View v, MotionEvent event){
testpoint(event);
return true;
}
private void testpoint(MotionEvent event){
if(!debugOn){
return;
}
//initialize mXs and mYs
ArrayList<Float> mXs = null;
ArrayList<Float> mYs = null;
if (mXs == null && mYs == null){
mXs = new ArrayList<Float>();
mYs = new ArrayList<Float>();
}
mXs.clear();
mYs.clear();
final int N = event.getPointerCount();
float x,y;
for(int i = 0; i < N; i++){
x = event.getX(event.getPointerId(i));
y = event.getY(event.getPointerId(i));
logd("x[" + i + "],y[" + i + "] = " + x + "," + y);
mXs.add(x);
mYs.add(y);
}
if(N > 0)m_view.setPoints(mXs,mYs);
}
}
private final boolean debugOn = true;
private final String TAG = "MyListener";
private int logd(String msg) {
int retVal = 0;
if (debugOn) {
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
Here is the class how to draw the point immediately.
public class svPaintCircle extends android.support.v7.widget.AppCompatImageView {
public svPaintCircle(Context context){
super(context);
}
public svPaintCircle(Context context, AttributeSet attrs) {super(context, attrs);}
public svPaintCircle(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
drawTouchPoint(canvas);
}
ArrayList<Float> mXs = null, mYs = null;
private boolean mDrawn = true;
private Paint mPointPaint = null;
private Paint mRectPaint = null;
private Paint mTextPaint = null;
public void setPoints(ArrayList<Float> mXs, ArrayList<Float> mYs){
if(debugOn) {
if(mPointPaint == null) {
mPointPaint = new Paint();
mPointPaint.setAntiAlias(false);
mPointPaint.setARGB(255,0,96,255);
mRectPaint = new Paint();
mRectPaint.setARGB(0x88,0x44,0x44,0x44); // 0x88 = 136 , 0x44 = 68
mTextPaint = new Paint();
mTextPaint.setTextSize(45);
mTextPaint.setARGB(0xff,0xff,0xff,0xff);
logd("init Paint");
}
this.mXs = mXs;
this.mYs = mYs;
mDrawn = false;
invalidate();
}
}
public void drawTouchPoint(Canvas canvas){
if(debugOn){
if(!mDrawn){
float x,y,rx,ry;
float dx = 80, dy = 80, r = 10;
for(int i = 0; i < mXs.size(); i++){
x = mXs.get(i);
y = mYs.get(i);
//draw cross
//canvas.drawLine(x, y - dy, x, y+dy, mPointPaint);
//canvas.drawLine(x - dx, y, x+dx ,y, mPointPaint);
canvas.drawCircle(x,y,r, mPointPaint);
rx = x;
ry = y - 40;
if(x + 75 > getRight())
rx = x -76;
if(ry < getTop())
ry = y + 20;
canvas.drawRect(0, 0, 320, 45, mRectPaint);
canvas.drawText("x: " + (int)x + " , y:" + (int)y, 0,35, mTextPaint);
}
mDrawn = true;
}
}
}
private final boolean debugOn = true;
private final String TAG = "PointView";
private int logd(String msg){
int retVal = 0;
if(debugOn){
retVal = Log.i(TAG, msg);
}
return retVal;
}
}
How can I make both TextView and CustomView shows together?
no, you can't. setContentView can only be done for one layout.
To add some value to my answer, I would assume your understanding of setContentView is a bit wrong. setContentView is how you tell android which layout file to associate with this activity (as per your example). that's how layouts with different components are done, it's one single file with multiple or different views inside one file (or being referenced from this file, with methods such as include in xml).
From the documentation:
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
https://developer.android.com/reference/android/app/Activity.html#setContentView(int)
I am new to programming and I am trying to implement a flood fill algorithm to colorize selected part in the image as a color book app.
I have found this link which provides full working code (but slow) for the algorithm. and also provide QueueLinearFloodFiller which is way faster.
The problem is that The custom MyView class is added to Relativelayout to show the bitmap that will be colored but the image is out of the view like this
I want to wrap it to fill the view and take its size like in wrap_content
I have tried to use this code to resize it
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
but it didn't work.
here is the full code and the XML
public class UnicornColorActivity extends AppCompatActivity {
private RelativeLayout dashBoard;
private MyView myView;
public ImageView image;
Button b_red, b_blue, b_green, b_orange, b_clear;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(R.layout.activity_unicorn_color);
findViewById(R.id.dashBoard);
b_red = (Button) findViewById(R.id.b_red);
b_blue = (Button) findViewById(R.id.b_blue);
b_green = (Button) findViewById(R.id.b_green);
b_orange = (Button) findViewById(R.id.b_orange);
b_red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF0000);
}
});
b_blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF0000FF);
}
});
b_green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFF00FF00);
}
});
b_orange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.changePaintColor(0xFFFF9900);
}
});
dashBoard = (RelativeLayout) findViewById(R.id.dashBoard);
int width = RelativeLayout.LayoutParams.WRAP_CONTENT;
int hight = RelativeLayout.LayoutParams.WRAP_CONTENT;
myView.setLayoutParams(new RelativeLayout.LayoutParams(width,hight));
dashBoard.addView(myView);
}
public class MyView extends View {
private Paint paint;
private Path path;
public Bitmap mBitmap;
public ProgressDialog pd;
final Point p1 = new Point();
public Canvas canvas;
//Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
this.paint = new Paint();
this.paint.setAntiAlias(true);
pd = new ProgressDialog(context);
this.paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.unicorn_2).copy(Bitmap.Config.ARGB_8888, true);
//Bitmap.createScaledBitmap(mBitmap, 60, 60 , false);
this.path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
this.paint.setColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
public void changePaintColor(int color){
this.paint.setColor(color);
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage("Filling....");
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
// flood fill
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor, int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0 && image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0 && image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1 && image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < (height - 1) && image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="542dp"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/selectableItemBackground"
app:cardBackgroundColor="#FFFFFF"
app:cardCornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="#+id/dashBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/b_red"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="10dp" >
</RelativeLayout>
</android.support.v7.widget.CardView>
<Button
android:id="#+id/b_red"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#FF0000" />
<Button
android:id="#+id/b_green"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_red"
android:background="#00FF00" />
<Button
android:id="#+id/b_blue"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_green"
android:background="#0000FF" />
<Button
android:id="#+id/b_orange"
android:layout_width="65dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/b_blue"
android:background="#FF9900" />
<Button
android:id="#+id/button5"
android:layout_width="60dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="Clear" />
Can Someone please help me to fix this
Im new on Stack Overflow!, I joined here for some problem that I got right now.
Im working with Android Studio where im trying to make a type of game that it requires a grid usage to start it. At this point im trying to implement the touch event on some bitmaps, those bitmaps are the tiles of my game but im kinda of confused, in My view, where I place all of the tiles i can get all of the coordinates (including height and width) of each tile, I check those values but when I apply the touch event (On Action Down) im getting the coords of my last tile of my grid. Thats strange, because when im drawing it in my canvas Im still got the actual values (the real coords) but in touch are different, im trying to figure this but no result at all.
Can someone here tell me where i go wrong?
Sorry for my english.
PS: The grid can be dragged.
MyView.java
package com.example.sammuzero.aplicamesta;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Map;
/**
* Created by lezama on 24-07-2017.
*/
public class MyView extends SurfaceView {
Bitmap piso1;
Bitmap muro;
Bitmap queso;
SurfaceHolder aguanta;
GameLoopThread loopGame;
Terreno pintaTerreno;
Sprite mouse;
boolean scroll;
float destinyX = 0;
float destinyY = 0;
float originX = 0;
float originY = 0;
float transX = 0;
float transY = 0;
float escala = 1;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
aguanta = getHolder();
loopGame = new GameLoopThread(this);
aguanta.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
loopGame.setRunning(true);
loopGame.start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
loopGame.setRunning(false);
while (retry) {
try {
loopGame.join();
retry = false;
} catch (InterruptedException e) {}
}
}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
queso = BitmapFactory.decodeResource(getResources(), R.drawable.kso);
pintaTerreno = new Terreno(0,0,new MapBit(piso1), new MapBit(muro));
}
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.scale(escala,escala);
canvas.translate((destinyX - originX), (destinyY - originY));
transX = (destinyX - originX);
transY = (destinyY - originY);
for(int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j ++){
dibujaCasilla(i,j, canvas);
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
}
}
canvas.scale(1.0f,1.0f);
//mouse.onDraw(canvas);
}
public void queTerrenoDibujo(Terreno e)
{
pintaTerreno = e;
}
public void setEscala(int escalaATransformar) {
float nuevaEscala;
nuevaEscala = (float) escalaATransformar / 100;
escala = nuevaEscala;
}
private void dibujaCasilla(int i, int j,Canvas canvas) {
// Primero revisa si hay una pared o no alli.
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
}
else {
pintaTerreno.getCasilla(i,j).getGrafico().setX(64 * i);
pintaTerreno.getCasilla(i,j).getGrafico().setY(64 * j);
pintaTerreno.getCasilla(i,j).getGrafico().onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
/*
MapBit nuevoBloque = null;
if (pintaTerreno.getCasilla(i,j).getRepresenta() == 'P') {
nuevoBloque = new MapBit((64 * i),(64 * j),muro);
nuevoBloque.onDraw(canvas);
}
else {
nuevoBloque = new MapBit((64 * i),(64 * j),piso1);
nuevoBloque.onDraw(canvas);
if(pintaTerreno.getCasilla(i,j).getRepresenta() == 'Q')
canvas.drawBitmap(queso,(64 * i) + 16, (64 * j) + 16, null);
}
*/
// Luego, asegurate de los elementos que estan en esa casilla.
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//return super.onTouchEvent(event);
int action = event.getAction();
if (action==MotionEvent.ACTION_MOVE){
destinyX = event.getX();
destinyY = event.getY();
}
else if (action==MotionEvent.ACTION_DOWN) {
Log.i("Probando X,Y en 0,0", "X: " + pintaTerreno.getCasilla(0, 0).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(0, 0).getGrafico().getY());
for (int i = 0; i < pintaTerreno.getAncho(); i++) {
for (int j = 0; j < pintaTerreno.getAlto(); j++) {
Log.i("Probando X,Y", "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX()
+ " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY());
String msg = "X: " + pintaTerreno.getCasilla(i, j).getGrafico().getX() + " Y: " + pintaTerreno.getCasilla(i, j).getGrafico().getY();
if (pintaTerreno.getCasilla(i, j).getGrafico().isCollition(event.getX(), event.getY())) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
}
}
originX = event.getX() - transX;
originY = event.getY() - transY;
scroll = true;
}
else if (action==MotionEvent.ACTION_UP){
transX = (destinyX - originX);
transY = (destinyY - originY);
scroll = false;
}
return true;
}
}
Terreno.java (The grid)
package com.example.sammuzero.aplicamesta;
import java.util.ArrayList;
import java.util.Random;
/**
*
* #author estudiante
*/
public class Terreno {
private ArrayList<Object> todo = new ArrayList<>();
private Casilla[][] plataforma;
private int alto;
private int ancho;
public Terreno (int alt, int anch, MapBit nada, MapBit pared)
{
int i;
int j;
this.plataforma = new Casilla[alt][anch];
this.alto = alt;
this.ancho = anch;
for(i = 0; i < this.alto; i++)
for(j = 0; j < this.ancho; j++)
this.plataforma[i][j] = new Casilla(i,j, nada);
this.inicializa(pared);
}
// Getters //
public int getAlto(){return this.alto;}
public int getAncho(){return this.ancho;}
public Casilla getCasilla(int i, int j){return this.plataforma[i][j];}
public ArrayList<Object> getTodo(){return this.todo;}
// Setters //
public void setEnCasilla(int x, int y, Object o, char r){this.plataforma[x][y].setObjeto(o,r);}
// Metodos //
public void inicializa(MapBit pared)
{
int cuantos = ((this.alto*this.ancho) * 10) / 100;
Random rand = new Random();
int llevo = 0;
int sel = 0;
for(int i = 0; i < this.alto ; i++)
for(int j = 0 ; j < this.ancho; j++)
{
sel = 1+rand.nextInt(10);
if(sel == 1 && llevo < cuantos)
{
Pared nueva = new Pared(this.plataforma[i][j]);
this.plataforma[i][j].setGrafico(pared);
todo.add(nueva);
llevo ++;
}
else if (sel == 10) {
Queso nuevo = new Queso(this.plataforma[i][j]);
todo.add(nuevo);
}
}
}
}
Casilla.java (the tile)
package com.example.sammuzero.aplicamesta;
import android.support.design.widget.Snackbar;
/**
* Created by lezama on 28-07-2017.
*/
public class Casilla {
private int posX;
private int posY;
private Object contenido;
private char representa;
private MapBit grafico;
public Casilla(int i, int j, MapBit graf)
{
this.posX = i;
this.posY = j;
this.representa = '0';
contenido = null;
this.grafico = graf;
}
public int getPosX() {return this.posX;}
public int getPosY() {return this.posY;}
public char getRepresenta() {return this.representa;}
public MapBit getGrafico() {return this.grafico;}
public void setObjeto(Object item , char rep)
{
this.contenido = item;
this.representa = rep;
}
public void setGrafico (MapBit grafico1) {this.grafico = grafico1;}
/*
public void onTouch()
{
Toast.makeText(this.getContext(), "X:"+this.posX+" Y:"+this.posY, Toast.LENGTH_SHORT).show();
} */
}
MapBit.java (where it resides my Bitmap)
package com.example.sammuzero.aplicamesta;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* TI, MapBit!
* Created by Samuzero15 on 28-07-2017.
*/
public class MapBit {
private float x;
private float y;
private int height;
private int width;
private Bitmap bmp;
public MapBit(Bitmap pmb)
{
this.bmp = pmb;
this.height = this.bmp.getHeight();
this.width = this.bmp.getWidth();
}
// Getmethis
public float getX(){return this.x;}
public float getY(){return this.y;}
public int getHeight(){return this.height;}
public int getWidth(){return this.width;}
public Bitmap getBitmap(){return this.bmp;}
public void setX(float newX){this.x = newX;}
public void setY(float newY){this.y = newY;}
public void onDraw(Canvas canvas)
{
canvas.drawBitmap(this.bmp,x,y,null);
}
public boolean isCollition(float x2, float y2) {
return x2 > this.x && x2 < this.x + this.width && y2 > this.y && y2 < this.y + this.height;
}
}
activity_main.xml (The main view for landscape)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_gravity="center"
tools:context="com.example.sammuzero.aplicamesta.MainActivity">
<RelativeLayout
android:layout_width="304dp"
android:layout_height="439dp"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:weightSum="1"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<view
android:id="#+id/game"
class="com.example.sammuzero.aplicamesta.MyView"
id="#+id/view4"
layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="356dp"
android:gravity="center" />
<SeekBar
android:id="#+id/zoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center"
android:max="150"
android:min="25"
android:progress="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<Button
android:id="#+id/exit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Salir" />
<Button
android:id="#+id/gatos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Gatos" />
<Button
android:id="#+id/reinicio"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Repetir" />
<ImageButton
android:id="#+id/nextTurn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:srcCompat="#android:drawable/ic_media_play" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
The main activity in java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
MyView elJuego;
Button salida;
Button reset;
Button nextTurn;
SeekBar escal;
Bitmap piso1;
Bitmap muro;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
salida = (Button) findViewById(R.id.exit);
reset = (Button) findViewById(R.id.reinicio);
elJuego = (MyView) findViewById(R.id.game);
escal = (SeekBar) findViewById(R.id.zoom);
salida.setOnClickListener(this);
reset.setOnClickListener(this);
escal.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progressChanged = 0;
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
progressChanged = progress;
elJuego.setEscala(progressChanged);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
piso1 = BitmapFactory.decodeResource(getResources(), R.drawable.floor1);
muro = BitmapFactory.decodeResource(getResources(), R.drawable.pared);
}
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.exit:
finish();
System.exit(0);
break;
case R.id.reinicio:
elJuego.invalidate();
Terreno nuevo = new Terreno(2,2,new MapBit(piso1) , new MapBit(muro));
elJuego.queTerrenoDibujo(nuevo);
default: break;
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
(JAVA FILE 1)
public class CropActivity extends Activity implements OnTouchListener {
public static final String RETURN_DATA = "return-data";
public static final String RETURN_DATA_AS_BITMAP = "data";
public static final String ACTION_INLINE_DATA = "inline-data";
private ImageView mImg;
private ImageView mTemplateImg;
// private static ProgressDialog mProgressDialog;
private Matrix mMatrix = new Matrix();
private float mScaleFactor = 0.8f;
private float mRotationDegrees = 0.f;
private float mFocusX = 0.f;
private float mFocusY = 0.f;
private int mImageHeight, mImageWidth;
private ScaleGestureDetector mScaleDetector;
private MoveGestureDetector mMoveDetector;
// Constants
public static final int MEDIA_GALLERY = 1;
public static final int TEMPLATE_SELECTION = 2;
public static final int DISPLAY_IMAGE = 3;
Bitmap profilePic;
String userImageLink;
int cropImageWidth;
int cropImageHeight;
int width, height, w1;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.crop_activity_layout);
Resources r = getResources();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
width = dm.widthPixels;
height = dm.heightPixels;
double fWidth = width * (0.70);
Log.d("Width is:- ", ">>>>>>>>>>>>>>>>" + fWidth);
w1 = (int) Math.round(fWidth);
Log.d("Width after roundin is:- ", ">>>>>>>>>>>>>>>>" + width);
cropImageWidth = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, w1, r.getDisplayMetrics());
// etc...
cropImageHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, w1, r.getDisplayMetrics());
int actionBarHeight = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 40, r.getDisplayMetrics());
userImageLink = getIntent().getStringExtra("path");
mImg = (ImageView) findViewById(R.id.cp_img);
mTemplateImg = (ImageView) findViewById(R.id.cp_face_template);
mImg.setOnTouchListener(this);
// Get screen size in pixels.
// DisplayMetrics metrics = new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(metrics);
// mScreenWidth = metrics.widthPixels;
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int statusBarHeight = (int) Math.ceil(25 * (getResources()
.getDisplayMetrics().density));
Log.e("size.x", "" + size.x);
Log.e("size.y", "" + (size.y - statusBarHeight - actionBarHeight));
// Set template image accordingly to device screen size.
Bitmap faceTemplate = BitmapFactory.decodeResource(getResources(),
R.drawable.four);
faceTemplate = Bitmap.createScaledBitmap(faceTemplate, cropImageWidth,
cropImageHeight, true);
mTemplateImg.setImageBitmap(faceTemplate);
// cropImageWidth = faceTemplate.getWidth();
// cropImageHeight = faceTemplate.getHeight();
// Log.e("getWidth", "" + faceTemplate.getWidth());
// Log.e("getHeight", "" + faceTemplate.getHeight());
File imgFile = new File("" + userImageLink);
if (imgFile.exists()) {
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile
.getAbsolutePath());
// Drawable d = new BitmapDrawable(getResources(), myBitmap);
mImg.setImageBitmap(myBitmap);
mImageHeight = myBitmap.getHeight();
mImageWidth = myBitmap.getWidth();
}
// View is scaled by matrix, so scale initially
mMatrix.postScale(mScaleFactor, mScaleFactor);
mImg.setImageMatrix(mMatrix);
// Setup Gesture Detectors
mScaleDetector = new ScaleGestureDetector(getApplicationContext(),
new ScaleListener());
mMoveDetector = new MoveGestureDetector(getApplicationContext(),
new MoveListener());
// Instantiate Thread Handler.
// mCropHandler = new CropHandler(this);
}
public void onCancelImageButton(View v) {
Intent intent = new Intent();
setResult(RESULT_CANCELED, intent);
finish();
}
public void onCropImageButton(View v) {
// Create progress dialog and display it.
// mProgressDialog = new ProgressDialog(v.getContext());
// mProgressDialog.setCancelable(false);
// mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
// mProgressDialog.setMessage("Please wait...");
// mProgressDialog.show();
// Setting values so that we can retrive the image from
// ImageView multiple times.
mImg.buildDrawingCache(true);
mImg.setDrawingCacheEnabled(true);
mTemplateImg.buildDrawingCache(true);
mTemplateImg.setDrawingCacheEnabled(true);
// Create new thread to crop.
new Thread(new Runnable() {
#Override
public void run() {
Bitmap croppedImg = null;
croppedImg = ImageProcess.cropImage(mImg.getDrawingCache(true),
mTemplateImg.getDrawingCache(true), cropImageWidth,
cropImageHeight);
mImg.setDrawingCacheEnabled(false);
mTemplateImg.setDrawingCacheEnabled(false);
if (croppedImg != null) {
// mProgressDialog.dismiss();
Utils.storeImage(croppedImg, "temp" + Const.ImageExtension);
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
} else {
// mProgressDialog.dismiss();
Intent intent = new Intent();
setResult(RESULT_CANCELED, intent);
finish();
}
}
}).start();
}
#SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
mMoveDetector.onTouchEvent(event);
float scaledImageCenterX = (mImageWidth * mScaleFactor) / 2;
float scaledImageCenterY = (mImageHeight * mScaleFactor) / 2;
mMatrix.reset();
mMatrix.postScale(mScaleFactor, mScaleFactor);
mMatrix.postRotate(mRotationDegrees, scaledImageCenterX,
scaledImageCenterY);
mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY
- scaledImageCenterY);
ImageView view = (ImageView) v;
view.setImageMatrix(mMatrix);
return true;
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
return true;
}
}
private class MoveListener extends
MoveGestureDetector.SimpleOnMoveGestureListener {
#Override
public boolean onMove(MoveGestureDetector detector) {
PointF d = detector.getFocusDelta();
mFocusX += d.x;
mFocusY += d.y;
return true;
}
}
}
(JAVA FILE 2)
public class ImageProcess {
public static Bitmap cropImage(Bitmap img, Bitmap templateImage, int width,
int height) {
// Merge two images together.
Bitmap bm = Bitmap.createBitmap(img.getWidth(), img.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas combineImg = new Canvas(bm);
combineImg.drawBitmap(img, 0f, 0f, null);
// Create new blank ARGB bitmap.
Bitmap finalBm = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
// Get the coordinates for the middle of combineImg.
int hMid = bm.getHeight() / 2;
int wMid = bm.getWidth() / 2;
int hfMid = finalBm.getHeight() / 2;
int wfMid = finalBm.getWidth() / 2;
finalBm = Bitmap.createBitmap(bm, (wMid - wfMid), (hMid - hfMid),
width, height);
// Get rid of images that we finished with to save memory.
img.recycle();
templateImage.recycle();
bm.recycle();
return finalBm;
}
}
(XML FILE 1)
<?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="vertical" >
<innovify.hustl.library.CustomTextView
android:id="#+id/fcp_info_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/cp_info_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1.0" >
<ImageView
android:id="#+id/cp_img"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:contentDescription="#string/cp_image_contentDesc"
android:scaleType="matrix" />
<ImageView
android:id="#+id/cp_face_template"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:contentDescription="#string/cp_template_contentDesc"
android:scaleType="centerInside"
android:src="#drawable/four" />
</FrameLayout>
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:orientation="horizontal" >
<innovify.hustl.library.CustomButton
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:background="#e2e2e2"
android:gravity="center"
android:onClick="onCancelImageButton"
android:text="#string/cancel" />
<innovify.hustl.library.CustomButton
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:background="#e2e2e2"
android:gravity="center"
android:onClick="onCropImageButton"
android:text="#string/cp_crop_button" />
</LinearLayout>
Output:
Got This Error:-
12-08 13:35:38.108: E/AndroidRuntime(15191): FATAL EXCEPTION: Thread-1317
12-08 13:35:38.108: E/AndroidRuntime(15191): java.lang.IllegalArgumentException: x must be >= 0
12-08 13:35:38.108: E/AndroidRuntime(15191): at android.graphics.Bitmap.checkXYSign(Bitmap.java:280)
12-08 13:35:38.108:
for custom shape in imageview,
you can use this lib
https://github.com/siyamed/android-shape-imageview
https://github.com/MostafaGazar/CustomShapeImageView
I have two seperate (x, y) points that I want to use to apply rotation to a view.
The first point is fixed, and I find the values of it fairly easily (for example 200,200). My second point is where a TOUCH is present, so I grab the RawX and RawY points easily as well. I feed these two points into this method that I found on another stack overflow question.
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (firstPointX - secondPointX);
double delta_y = (firstPointY - secondPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
and I use the return of that to set the rotation of a View. Like so myView.setRotation(...). The result ends up being a crazy spinning view while I move the cursor/finger on the screen. Any ideas?
The two points I'm grabbing seem to be correct, leaving me guessing that maybe the findRotation method is incorrect.
My activity:
public class MainActivity extends Activity {
ImageView imageView;
ImageView dragHandle;
RelativeLayout layout;
int rememberAngle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
dragHandle = (ImageView) findViewById(R.id.imageView2);
layout = (RelativeLayout) findViewById(R.id.relativeLayout2);
resize(dragHandle);
}
public void resize(ImageView resizeButton) {
resizeButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
int firstPointX = locationOfLayout[0];
int firstPointY = locationOfLayout[1];
int secondPointX = dragHandle.getWidth() / 2 + locationOfDrag[0];
int secondPointY = dragHandle.getHeight() / 2 + locationOfDrag[1];
rememberAngle = (int) findRotation(firstPointX, firstPointY, secondPointX, secondPointY) + layout.getRotation();
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
int centerXOnLayout = layout.getWidth() / 2 + locationOfLayout[0];
int centerYOnLayout = layout.getHeight() / 2 + locationOfLayout[1];
int centerXOnDrag = dragHandle.getWidth() / 2 + locationOfDrag[0];
int centerYOnDrag = dragHandle.getHeight() / 2 + locationOfDrag[1];
layout.setRotation(findRotation(centerXOnLayout, centerYOnLayout, centerXOnDrag, centerYOnDrag) - rememberAngle);
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (secondPointX - firstPointX);
double delta_y = (secondPointY - firstPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
}
My 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" >
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/ic_launcher" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_below="#+id/imageView1"
android:layout_toRightOf="#+id/imageView1"
android:src="#drawable/meanicons" />
</RelativeLayout>
</RelativeLayout>
public void resize(ImageView resizeButton) {
resizeButton.setOnTouchListener(new View.OnTouchListener() {
float startAngle;
float zeroAngle;
int firstPointX;
int firstPointY;
public boolean onTouch(View v, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
firstPointX = locationOfLayout[0];
firstPointY = locationOfLayout[1];
int secondPointX = motionEvent.getRawX();
int secondPointY = motionEvent.getRawY();
zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY) // remember "zero" angle
startAngle = layout.getRotation(); // remember angle at which layout is rotated at the start
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
layout.setRotation(findRotation(firstPointX, firstPointY, motionEvent.getRawX(), motionEvent.getRawY()) - zeroAngle + startAngle); // rotate relative to start and zero angle
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
private float findRotation(int firstPointX, int firstPointY, int secondPointX, int secondPointY) {
double delta_x = (secondPointX - firstPointX);
double delta_y = (secondPointY - firstPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}