Java – Android – create animated images of simulation type for mobile
I want to create a controller like simulator to move my character in the XML layout (which looks like Playstation or X@R_153_2419 @Similar on controller – circular simulation)
My first plan was to simply use the image view and place four transparent buttons on the image view to allow movement, but it was a bit boring and wanted to be really creative, but I was hard to find any type of document and wasn't sure where to start
Basically, what I'm looking for is an image that looks like a simulation (see below), and then the user can press and move the animation, which will trigger the relevant position movement Ideally, I would also like to have this, so that users can automatically animate by clicking on the right side of the simulation, and then trigger the correct action
I'm not sure if this is feasible. I want to implement it in my XML layout, or if it's easier, it can be created programmatically
Solution
See the last edit
----------------------------------------------
You must implement gesturedetector Ongesturelistener interface, and use ondown and onscroll methods to detect gestures, and then use the OnDraw (canvas C) method of the view to redraw the simulated bitmap (and convert it) after modifying its position (if you want to use matrix)
You can also use ontouchevent: onup event on gesturedetector in this answer
---------------------------------------------------------------------------------------
Edit this is an attempt, not a bitmap, but a drawcircle method:
It's not too complicated. I write it very fast, so it must be improved, but its working principle is very good:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class AnalogueView extends View { float x,y; double r,t; int cx,cy,w,h; final int RADIUS = 20; Paint black = new Paint(); Paint grey = new Paint(); Paint white = new Paint(); private int toDo; public AnalogueView(Context context,AttributeSet attrs) { super(context,attrs); black.setColor(Color.BLACK); grey.setColor(Color.GRAY); white.setColor(Color.WHITE); black.setFlags(Paint.ANTI_ALIAS_FLAG); white.setFlags(Paint.ANTI_ALIAS_FLAG); grey.setFlags(Paint.ANTI_ALIAS_FLAG); } @Override protected void onSizeChanged(int w,int h,int oldw,int oldh) { this.w = w; this.h = h; cx = w/2; cy = h/2; x = cx;y=cy; super.onSizeChanged(w,h,oldw,oldh); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawMyStuff(canvas); switch (toDo) { case 1: center(); break; default: break; } } private void drawMyStuff(final Canvas canvas) { canvas.drawCircle(cx,w/2,black); canvas.drawCircle(cx,w/2-5,grey); canvas.drawCircle(cx,w/2-10,black); canvas.drawCircle(x,y,RADIUS+2,white); canvas.drawCircle(x,RADIUS,grey); } // n2p : normal to polar coordinates conversion // p2n : polar to normal coordinates conversion // R : distance to polar center // T : polar angle double n2pR(double x,double y){ return distance(x,cx,cy); } double n2pT(double x,double y){ return Math.atan2((y-cy),(x-cx)); } double p2nX(double r,double t){ return r*Math.cos(t) + cx; } double p2nY(double r,double t){ return r*Math.sin(t) + cy; } double n2pR(){ return distance(x,cy); } double n2pT(){ return Math.atan2((y-cy),(x-cx)); } double p2nX(){ return r*Math.cos(t) + cx; } double p2nY(){ return r*Math.sin(t) + cy; } double distance(double x1,double y1,double x2,double y2 ){ return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2)); } @Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()){ case MotionEvent.ACTION_DOWN : updatePosition(event); break; case MotionEvent.ACTION_MOVE : updatePosition(event); break; case MotionEvent.ACTION_UP : toDo = 1; center(); break; default :break; } return true; } private void center(){ if(r>15){ r-=15; }else{ toDo=0; r=0; } x = (float) p2nX(); y= (float) p2nY(); invalidate(); } void updatePosition(MotionEvent e){ r= Math.min(w/2-RADIUS,n2pR(e.getX(),e.getY())); t = n2pT(e.getX(),e.getY()); x = (float) p2nX(); y =(float) p2nY(); invalidate(); } }
This is how to add it to the layout:
<yourpackage.AnalogueView android:id="@+id/analogueView1" android:layout_width="80px" android:layout_height="80px" />
In order to detect different simulated events, you can add a listener with the required method definition and use the interface in analogview. Then, when you want to implement the behavior of analogview, you just need to add an implementation for the interface by calling setter (it is similar to setonclicklistener of button) In this way, you will have a fully encapsulated analogview that you can reuse in any other application
-------------------------------------------------------------------------------
Last edit: use listener to handle events:
I embedded a listener using analogueview. Now you can use it like onclicklistener,
The setonmovelistener method is used to provide the implementation of two methods:
onMaxMoveInDirection(double polar_angle_of_direction) and onHalfMoveInDirection(double polar_angle_of_direction)
This is the new code of analogueview (there is no major modification, but the interface definition, movelistener field and trigger the action in updateposition):
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class AnalogueView extends View { OnMoveListener moveListener; float x,e.getY()); x = (float) p2nX(); y =(float) p2nY(); if(moveListener != null) if(r == w/2-RADIUS) moveListener.onMaxMoveInDirection(t); else if(r >= w/4-RADIUS/2) moveListener.onHalfMoveInDirection(t); invalidate(); } public void setOnMoveListener(OnMoveListener listener){ moveListener =listener; } public interface OnMoveListener{ public void onHalfMoveInDirection(double polarAngle); public void onMaxMoveInDirection(double polarAngle); } }
Here is how to provide implementation:
import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import com.analog.AnalogueView.OnMoveListener; public class MainActivity extends Activity { AnalogueView analogue; TextView showMoveEvent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); showMoveEvent = (TextView) findViewById(R.id.showMoveEvent); analogue = (AnalogueView) findViewById(R.id.analogueView1); analogue.setOnMoveListener(new OnMoveListener() { @Override public void onMaxMoveInDirection(double polarAngle) { showMoveEvent.setText("max move in "+polarAngle+" direction"); } @Override public void onHalfMoveInDirection(double polarAngle) { showMoveEvent.setText("half move in "+polarAngle+" direction"); } }); } }
Result: display the event in the text field: