create rototable circle in android using Canvas - android

Guys I know How to draw circle in android..But what I need is using onTouch method to rotate that circle depending on the user hand movement on that circle. Please help.
public class MainActivity extends Activity {
public class SampleView extends View {
Paint mPaint = new Paint();
private Animation anim;
public SampleView(Context context) {
super(context);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(10);
mPaint.setColor(Color.RED);
}
private void createAnimation(Canvas canvas) {
anim = new RotateAnimation(0, 360, getWidth()/2, getHeight()/2);
anim.setRepeatMode(Animation.RESTART);
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(10000L);
startAnimation(anim);
}
protected void onDraw(Canvas canvas) {
int cx = getWidth()/2; // x-coordinate of center of the screen
int cy = getHeight()/2; // y-coordinate of the center of the screen
// Starts the animation to rotate the circle.
if (anim == null)
createAnimation(canvas);
canvas.drawCircle(cx, cy, 150, mPaint); // drawing the circle.
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
}

First, we have to determine the angle between old and new position of circle (as below figure).
cos a = uv / (|u|*|v|)
The simple equation may be
double tx = touch_x - center_x, ty = touch_y - center_y;
double t_length = Math.sqrt(tx*tx + ty*ty);
double angle = Math.acos(ty / t_length);
Then to rotate your Canvas. you can use the code
canvas.rotate(angle);
Or you can use another method as
public int touch_x,touch_y,cx,cy;
public float angle=0;
#Override
public boolean onTouchEvent(MotionEvent event) {
touch_x = (int)event.getX();
touch_y = (int)event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
//double tx = touch_x - cx, ty = touch_y - cy;
// double t_length = Math.sqrt(tx*tx + ty*ty);
//angle = (float) Math.acos(ty / t_length);
double dx = touch_x - cx;
// Minus to correct for coord re-mapping
double dy = -touch_y - cy;
double inRads = Math.atan2(dy,dx);
// We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12 O'clock
if (inRads < 0)
inRads = Math.abs(inRads);
else
inRads = 2*Math.PI - inRads;
angle= (float) Math.toDegrees(inRads);
return false;
}

Related

Android: How to draw circle within two point?

this is my current code
Path path_eclipse = new Path();
float radius = (float) (Math.sqrt(Math.pow(r.stopX - r.startX, 2.0f) + Math.pow(r.stopY - r.startY, 2.0f)) / 2.0f);
path_eclipse.addCircle(r.startX, r.startY, radius, Path.Direction.CCW);
canvas.drawPath(path_eclipse, paint);
with this code I am getting as output:
But I want to draw circle like this:
UPDATED Source code: This source code worked in my case
[SOLVED]
[OnDraw]
#Override
protected void onDraw(Canvas canvas) {
Path path_eclipse = new Path();
float centerX = (r.startX + r.stopX) /2;
float centerY = (r.startY + r.stopY) /2;
float radius = (float)Math.sqrt((r.stopX - r.startX)*(r.stopX - r.startX)+(r.stopY - r.startY)*(r.stopY - r.startY));
path_eclipse.addCircle(centerX, centerY, radius/2, Path.Direction.CCW);
canvas.drawPath(path_eclipse,paint);
}
[OnTouchEvent]
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = eventX;
startY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
stopX = eventX;
stopY = eventY;
break;
case MotionEvent.ACTION_UP:
stopX = eventX;
stopY = eventY;
break;
default:
return false;
}
invalidate();
return true;
}
The first two paramateres of addCircle are the x and y coordinates of the center. Assuming A and B are the furthest distance from each other on the circle you want, then the center should a point equidistant to both, hence:
float centerX = (pointA.x + pointB.x) /2
float centerY = (pointA.y + pointB.y) /2
And your radius should be, the distance between A and B, thus:
float radius = (Math.sqrt(Math.pow(x2−x1, 2) + Math.pow(y2−y1, 2))) / 2
Mid points
int mx=(r.stopX + r.startX)/2;
int my= (r.stopy+r.startY)/2;
Radius
float radius = Math.sqrt(Math.pow(r.stopX - my, 2)
+ Math.pow(r.stopY - my, 2));
Edited
I have used code below
public class CustomView extends View {
private Paint paint;
private Circle circle;
private List<Point> points;
public final int CIRCLE_BETWEEN_TWO_POINTS = 1;
private int viewType;
{
paint = new Paint();
points = new ArrayList<>();
}
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
switch (viewType) {
case CIRCLE_BETWEEN_TWO_POINTS:
drawView(canvas);
break;
}
}
private void drawView(Canvas canvas){
for(Point point:points){
drawCircle(canvas,new Circle(point.x,point.y,10),false);
}
drawCircle(canvas,circle,true);
}
private void drawCircle(Canvas canvas,Circle circle, boolean isStroke){
paint.reset();
paint.setAntiAlias(true);
if(isStroke){
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
}else {
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
}
canvas.drawCircle(circle.getX(), circle.getY(), circle.getRadius(), paint);
}
public void drawCircleBetweenTwoPoints(int x1, int y1, int x2, int y2) {
viewType = CIRCLE_BETWEEN_TWO_POINTS;
points.clear();
points.add(new Point(x1, y1));
points.add(new Point(x2, y2));
int mx = (x1 + x2) / 2;
int my = (y1 + y2) / 2;
double radius = Math.sqrt(Math.pow(x1 - mx, 2)
+ Math.pow(y1 - my, 2));
circle=new Circle(mx,my,(int)radius);
invalidate();
}
}
And called method as
customView.drawCircleBetweenTwoPoints(500,200,100,600);
and its working for me
Click to see output
If you want to draw circle like this, you must know 3 points, then calculate center with radius. Because two points cannot uniquely determine a circle. You can find only whole line of possible centers.
On the other hand, if we consider that two points are exactly opposite. Then you should calculate center by midpoint formula:
M = [(x1 + x2 / 2), (y1 + y2 / 2)]
Next, you can do the same thing as at first case. First, calculate radius and then draw circle.
Assuming, that A and B are exactly opposite to each other, the line segment defined by them will pass through the centre of the circle (C), and the latter will cut AB in half.
Thus:
You calculate then distance of the two points, and divide by two. So you'll have the radius.
The centre of the circle will be exactly halfway between the two: x=(x1+x2)/2 and y=(y1+y2)/2.
If they happen to be just random points, you can use one of these techniques:
Link
Link
In this case however, your problem is slightly tricky, as two points and a radius will not determine one circle unambiguously: the problem will have two solutions.

Oval path Animation using image

I am trying to implement Oval path animation, I want to show path animation using image, I tried https://github.com/matthewrkula/AnimatedPathView but it's not work for oval. I also tried below code for oval path but it is shows circle, Anyone have an idea? Thanks in advance!!!
MyAnimation.java
public class MyAnimation extends Animation {
private View view;
private float cx, cy; // center x,y position of circular path
private float prevX, prevY; // previous x,y position of image during animation
private float r; // radius of circle
private float prevDx, prevDy;
/**
* #param view - View that will be animated
* #param r - radius of circular path
*/
public MyAnimation(View view, float r){
this.view = view;
this.r = r;
}
#Override
public boolean willChangeBounds() {
return true;
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
// calculate position of image center
int cxImage = width / 2;
int cyImage = height / 1;
cx = view.getLeft() + cxImage;
cy = view.getTop() + cyImage;
// set previous position to center
prevX = cx;
prevY = cy;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 0){
t.getMatrix().setTranslate(prevDx, prevDy);
return;
}
float angleDeg = (interpolatedTime * 360f + 90) % 360;
float angleRad = (float) Math.toRadians(angleDeg);
// r = radius, cx and cy = center point, a = angle (radians)
float x = (float) (cx + r * Math.cos(angleRad));
float y = (float) (cy + r * Math.sin(angleRad));
float dx = prevX - x;
float dy = prevY - y;
prevX = x;
prevY = y;
prevDx = dx;
prevDy = dy;
t.getMatrix().setTranslate(dx, dy);
}
}
PathAnimation.java
image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Animation anim = new MyAnimation(image, 300);
anim.setDuration(1000);
image.startAnimation(anim);
}
});
I have found the solution after many tried using this custom class
AnimationView.java
public class AnimationView extends View {
Paint paint;
long animationDuration = 10000;
int framesPerSecond = 60;
Bitmap bm;
int bm_offsetX, bm_offsetY;
Path animPath;
PathMeasure pathMeasure;
float pathLength;
float step; //distance each step
float distance; //distance moved
float[] pos;
float[] tan;
Matrix matrix;
public AnimationView(Context context) {
super(context);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
initMyView();
}
public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initMyView();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void initMyView(){
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
bm_offsetX = bm.getWidth()/2;
bm_offsetY = bm.getHeight()/2;
animPath = new Path();
animPath.moveTo(100, 100);
animPath.addArc(new RectF(1, 100, 300, 600), 1, 800);
animPath.close();
pathMeasure = new PathMeasure(animPath, false);
pathLength = pathMeasure.getLength();
Toast.makeText(getContext(), "pathLength: " + pathLength, Toast.LENGTH_LONG).show();
step = 1;
distance = 0;
pos = new float[2];
tan = new float[2];
matrix = new Matrix();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(animPath, paint);
if(distance < pathLength){
pathMeasure.getPosTan(distance, pos, tan);
matrix.reset();
float degrees = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
matrix.postRotate(degrees, bm_offsetX, bm_offsetY);
matrix.postTranslate(pos[0]-bm_offsetX, pos[1]-bm_offsetY);
canvas.drawBitmap(bm, matrix, null);
distance += step;
}else{
distance = 0;
}
invalidate();
}
}
and put into xml
<com.example.android.mydemo.animation.pathanimation.AnimationView
android:layout_width="match_parent"
android:layout_height="450dp" />

Custom shape button

I am trying to make each slice of the pie a button. The pie is a bunch of vector drawables in an image view. I don't necessarily need the actual pie slices to be clicked. I was thinking of using Path to draw a transparent shape and place it on top and make that the button, but from what I understand, drawables aren't clickable.
I read one blog post that apparently used paths to make a custom shaped image view, and I know image views are clickable, but it seems like with the implementation in the blog post the image views are still rectangular, but the bitmaps the blogger was using in the example were just trimmed to a custom shape inside the image view. This is the post I'm referring to: http://www.androidhub4you.com/2014/10/android-custom-shape-imageview-rounded.html
Please explain this to me like a five year old. I'm relatively new to programming. Were it not for Android Studio's automatic everything, I would not be here.
Thank you.
You can just using drawArc and drawCircle to draw a radial menu, and using distance between touch point and center point and angle to detect which slice is currently being click. I wrote a Sample for you:
public class RadioButtons extends View {
//the number of slice
private int mSlices = 6;
//the angle of each slice
private int degreeStep = 360 / mSlices;
private int quarterDegreeMinus = -90;
private float mOuterRadius;
private float mInnerRadius;
//using radius square to prevent square root calculation
private float outerRadiusSquare;
private float innerRadiusSquare;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF mSliceOval = new RectF();
private static final double quarterCircle = Math.PI / 2;
private float innerRadiusRatio = 0.3F;
//color for your slice
private int[] colors = new int[]{Color.GREEN, Color.GRAY, Color.BLUE, Color.CYAN, Color.DKGRAY, Color.RED};
private int mCenterX;
private int mCenterY;
private OnSliceClickListener mOnSliceClickListener;
private int mTouchSlop;
private boolean mPressed;
private float mLatestDownX;
private float mLatestDownY;
public interface OnSliceClickListener{
void onSlickClick(int slicePosition);
}
public RadioButtons(Context context){
this(context, null);
}
public RadioButtons(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
public RadioButtons(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mTouchSlop = viewConfiguration.getScaledTouchSlop();
mPaint.setStrokeWidth(10);
}
public void setOnSliceClickListener(OnSliceClickListener onSliceClickListener){
mOnSliceClickListener = onSliceClickListener;
}
#Override
public void onSizeChanged(int w, int h, int oldw, int oldh){
mCenterX = w / 2;
mCenterY = h / 2;
mOuterRadius = mCenterX > mCenterY ? mCenterY : mCenterX;
mInnerRadius = mOuterRadius * innerRadiusRatio;
outerRadiusSquare = mOuterRadius * mOuterRadius;
innerRadiusSquare = mInnerRadius * mInnerRadius;
mSliceOval.left = mCenterX - mOuterRadius;
mSliceOval.right = mCenterX + mOuterRadius;
mSliceOval.top = mCenterY - mOuterRadius;
mSliceOval.bottom = mCenterY + mOuterRadius;
}
#Override
public boolean onTouchEvent(MotionEvent event){
float currX = event.getX();
float currY = event.getY();
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:
mLatestDownX = currX;
mLatestDownY = currY;
mPressed = true;
break;
case MotionEvent.ACTION_MOVE:
if(Math.abs(currX - mLatestDownX) > mTouchSlop || Math.abs(currY - mLatestDownY) > mTouchSlop) mPressed = false;
break;
case MotionEvent.ACTION_UP:
if(mPressed){
int dx = (int) currX - mCenterX;
int dy = (int) currY - mCenterY;
int distanceSquare = dx * dx + dy * dy;
//if the distance between touchpoint and centerpoint is smaller than outerRadius and longer than innerRadius, then we're in the clickable area
if(distanceSquare > innerRadiusSquare && distanceSquare < outerRadiusSquare){
//get the angle to detect which slice is currently being click
double angle = Math.atan2(dy, dx);
if(angle >= -quarterCircle && angle < 0){
angle += quarterCircle;
}else if(angle >= -Math.PI && angle < -quarterCircle){
angle += Math.PI + Math.PI + quarterCircle;
}else if(angle >= 0 && angle < Math.PI){
angle += quarterCircle;
}
double rawSliceIndex = angle / (Math.PI * 2) * mSlices;
if(mOnSliceClickListener != null){
mOnSliceClickListener.onSlickClick((int) rawSliceIndex);
}
}
}
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas){
int startAngle = quarterDegreeMinus;
//draw slice
for(int i = 0; i < mSlices; i++){
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(colors[i % colors.length]);
canvas.drawArc(mSliceOval, startAngle, degreeStep, true, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
canvas.drawArc(mSliceOval, startAngle, degreeStep, true, mPaint);
startAngle += degreeStep;
}
//draw center circle
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLACK);
canvas.drawCircle(mCenterX, mCenterY, mInnerRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
canvas.drawCircle(mCenterX, mCenterY, mInnerRadius, mPaint);
}
}

Is there a way to getPixel(x,y) without a bitmap? [duplicate]

I am trying to make each slice of the pie a button. The pie is a bunch of vector drawables in an image view. I don't necessarily need the actual pie slices to be clicked. I was thinking of using Path to draw a transparent shape and place it on top and make that the button, but from what I understand, drawables aren't clickable.
I read one blog post that apparently used paths to make a custom shaped image view, and I know image views are clickable, but it seems like with the implementation in the blog post the image views are still rectangular, but the bitmaps the blogger was using in the example were just trimmed to a custom shape inside the image view. This is the post I'm referring to: http://www.androidhub4you.com/2014/10/android-custom-shape-imageview-rounded.html
Please explain this to me like a five year old. I'm relatively new to programming. Were it not for Android Studio's automatic everything, I would not be here.
Thank you.
You can just using drawArc and drawCircle to draw a radial menu, and using distance between touch point and center point and angle to detect which slice is currently being click. I wrote a Sample for you:
public class RadioButtons extends View {
//the number of slice
private int mSlices = 6;
//the angle of each slice
private int degreeStep = 360 / mSlices;
private int quarterDegreeMinus = -90;
private float mOuterRadius;
private float mInnerRadius;
//using radius square to prevent square root calculation
private float outerRadiusSquare;
private float innerRadiusSquare;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF mSliceOval = new RectF();
private static final double quarterCircle = Math.PI / 2;
private float innerRadiusRatio = 0.3F;
//color for your slice
private int[] colors = new int[]{Color.GREEN, Color.GRAY, Color.BLUE, Color.CYAN, Color.DKGRAY, Color.RED};
private int mCenterX;
private int mCenterY;
private OnSliceClickListener mOnSliceClickListener;
private int mTouchSlop;
private boolean mPressed;
private float mLatestDownX;
private float mLatestDownY;
public interface OnSliceClickListener{
void onSlickClick(int slicePosition);
}
public RadioButtons(Context context){
this(context, null);
}
public RadioButtons(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
public RadioButtons(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mTouchSlop = viewConfiguration.getScaledTouchSlop();
mPaint.setStrokeWidth(10);
}
public void setOnSliceClickListener(OnSliceClickListener onSliceClickListener){
mOnSliceClickListener = onSliceClickListener;
}
#Override
public void onSizeChanged(int w, int h, int oldw, int oldh){
mCenterX = w / 2;
mCenterY = h / 2;
mOuterRadius = mCenterX > mCenterY ? mCenterY : mCenterX;
mInnerRadius = mOuterRadius * innerRadiusRatio;
outerRadiusSquare = mOuterRadius * mOuterRadius;
innerRadiusSquare = mInnerRadius * mInnerRadius;
mSliceOval.left = mCenterX - mOuterRadius;
mSliceOval.right = mCenterX + mOuterRadius;
mSliceOval.top = mCenterY - mOuterRadius;
mSliceOval.bottom = mCenterY + mOuterRadius;
}
#Override
public boolean onTouchEvent(MotionEvent event){
float currX = event.getX();
float currY = event.getY();
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:
mLatestDownX = currX;
mLatestDownY = currY;
mPressed = true;
break;
case MotionEvent.ACTION_MOVE:
if(Math.abs(currX - mLatestDownX) > mTouchSlop || Math.abs(currY - mLatestDownY) > mTouchSlop) mPressed = false;
break;
case MotionEvent.ACTION_UP:
if(mPressed){
int dx = (int) currX - mCenterX;
int dy = (int) currY - mCenterY;
int distanceSquare = dx * dx + dy * dy;
//if the distance between touchpoint and centerpoint is smaller than outerRadius and longer than innerRadius, then we're in the clickable area
if(distanceSquare > innerRadiusSquare && distanceSquare < outerRadiusSquare){
//get the angle to detect which slice is currently being click
double angle = Math.atan2(dy, dx);
if(angle >= -quarterCircle && angle < 0){
angle += quarterCircle;
}else if(angle >= -Math.PI && angle < -quarterCircle){
angle += Math.PI + Math.PI + quarterCircle;
}else if(angle >= 0 && angle < Math.PI){
angle += quarterCircle;
}
double rawSliceIndex = angle / (Math.PI * 2) * mSlices;
if(mOnSliceClickListener != null){
mOnSliceClickListener.onSlickClick((int) rawSliceIndex);
}
}
}
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas){
int startAngle = quarterDegreeMinus;
//draw slice
for(int i = 0; i < mSlices; i++){
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(colors[i % colors.length]);
canvas.drawArc(mSliceOval, startAngle, degreeStep, true, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
canvas.drawArc(mSliceOval, startAngle, degreeStep, true, mPaint);
startAngle += degreeStep;
}
//draw center circle
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.BLACK);
canvas.drawCircle(mCenterX, mCenterY, mInnerRadius, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.WHITE);
canvas.drawCircle(mCenterX, mCenterY, mInnerRadius, mPaint);
}
}

rotate dial in limited degrees

All I want rotate image in particular angle as like below image. I have code for rotation but it rotate 360 degree but I want it only for particular degrees and get the selected number which is upper side of dial.
below is my code.
My custom View this work fine but lake of perfomance.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
public class MyDialView extends View implements OnGestureListener{
private static Bitmap bimmap;
private static Paint paint;
private static Rect bounds;
private int totalNicks = 100;
private int currentNick = 0;
private GestureDetector gestureDetector;
private float dragStartDeg = Float.NaN;
float dialerWidth = 0,dialerHeight = 0;
private static Paint createDefaultPaint() {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
return paint;
}
private float xyToDegrees(float x, float y) {
float distanceFromCenter = PointF.length((x - 0.5f), (y - 0.5f));
if (distanceFromCenter < 0.1f
|| distanceFromCenter > 0.5f) { // ignore center and out of bounds events
return Float.NaN;
} else {
return (float) Math.toDegrees(Math.atan2(x - 0.5f, y - 0.5f));
}
}
public final float getRotationInDegrees() {
return (360.0f / totalNicks) * currentNick;
}
public final void rotate(int nicks) {
currentNick = (currentNick + nicks);
if (currentNick >= totalNicks) {
currentNick %= totalNicks;
} else if (currentNick < 0) {
currentNick = (totalNicks + currentNick);
}
Log.e("Current nick", String.valueOf(currentNick));
if((currentNick > 80 || currentNick < 20)){
invalidate();
}
}
public MyDialView(Context context, AttributeSet attrs) {
super(context, attrs);
bimmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.out_round);
paint = createDefaultPaint();
gestureDetector = new GestureDetector(getContext(), this);
dialerWidth = bimmap.getWidth() /2.0f;
dialerHeight = bimmap.getHeight() / 2.0f;
bounds = new Rect();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.getClipBounds(bounds);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
//{
canvas.translate(bounds.left, bounds.top);
float rotation = getRotationInDegrees();
canvas.rotate(rotation, dialerWidth, dialerHeight);
canvas.drawBitmap(bimmap, 0,0,null);
//canvas.rotate(- rotation, dialerWidth, dialerHeight);
//}
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
} else {
return super.onTouchEvent(event);
}
}
//Gesture detector methods
#Override
public boolean onDown(MotionEvent e) {
float x = e.getX() / ((float) getWidth());
float y = e.getY() / ((float) getHeight());
dragStartDeg = xyToDegrees(x, y);
//Log.d("deg = " , ""+dragStartDeg);
if (! Float.isNaN(dragStartDeg)) {
return true;
} else {
return false;
}
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
#Override
public void onLongPress(MotionEvent e) {
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
if (! Float.isNaN(dragStartDeg)) {
float currentDeg = xyToDegrees(e2.getX() / getWidth(),
e2.getY() / getHeight());
if (! Float.isNaN(currentDeg)) {
float degPerNick = 360.0f / totalNicks;
float deltaDeg = dragStartDeg - currentDeg;
final int nicks = (int) (Math.signum(deltaDeg)
* Math.floor(Math.abs(deltaDeg) / degPerNick));
if (nicks != 0) {
dragStartDeg = currentDeg;
rotate(nicks);
}
}
return true;
} else {
return false;
}
}
#Override
public void onShowPress(MotionEvent e) {
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
}
I want 0-9 according to user selection & also allow user rotation to 0-9 not more rotation.
I have also check another code this is below.
dialer = (ImageView) findViewById(R.id.imageView_ring);
dialer.setOnTouchListener(new MyOnTouchListener());
dialer.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// method called more than once, but the values only need to be initialized one time
if (dialerHeight == 0 || dialerWidth == 0) {
dialerHeight = dialer.getHeight();
dialerWidth = dialer.getWidth();
// resize
Matrix resize = new Matrix();
resize.postScale((float)Math.min(dialerWidth, dialerHeight) / (float)imageOriginal.getWidth(), (float)Math.min(dialerWidth, dialerHeight) / (float)imageOriginal.getHeight());
imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false);
// translate to the image view's center
float translateX = dialerWidth / 2 - imageScaled.getWidth() / 2;
float translateY = dialerHeight / 2 - imageScaled.getHeight() / 2;
matrix.postTranslate(translateX, translateY);
dialer.setImageBitmap(imageScaled);
dialer.setImageMatrix(matrix);
Log.e("Rotation degree :"+rotationDegrees, String.valueOf(tickNumber));
}
}
});
int tickNumber = 0;
private void rotateDialer(float degrees) {
//System.out.println("Rotation Done :: "+rotationDone);
// if(!rotationDone) {
this.rotationDegrees += degrees;
this.rotationDegrees = this.rotationDegrees % 360;
tickNumber = (int)this.rotationDegrees*100/360;
// It could be negative
if (tickNumber > 0) tickNumber = 100 - tickNumber;
//this.rotationDegrees = Math.abs(rotationDegrees);
this.tickNumber = Math.abs(tickNumber);
if(tickNumber < 20 || tickNumber > 80){
Log.e("Rotation degree :"+rotationDegrees, String.valueOf(tickNumber));
matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);
dialer.setImageMatrix(matrix);
}
// }
}
/**
* #return The angle of the unit circle with the image view's center
*/
private double getAngle(double xTouch, double yTouch) {
double delta_x = xTouch - (dialerWidth) /2;
double delta_y = (dialerHeight) /2 - yTouch;
double radians = Math.atan2(delta_y, delta_x);
double dx = xTouch - dWidth;
double dy = (dHeight - ((dialerHeight) /2)) - yTouch;
double dRadi = Math.atan2(dy, dx);
//Log.e("MY degree", String.valueOf( Math.toDegrees(dRadi)));
//return Math.toDegrees(dRadi);
return Math.toDegrees(radians);
}
/**
* Simple implementation of an {#link OnTouchListener} for registering the dialer's touch events.
*/
private class MyOnTouchListener implements OnTouchListener {
private double startAngle;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// reset the touched quadrants
/*for (int i = 0; i < quadrantTouched.length; i++) {
quadrantTouched[i] = false;
}*/
//allowRotating = false;
startAngle = getAngle(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
/*double rotationAngleRadians = Math.atan2(event.getX() - (dialer.getWidth() / 2 ), ( (dialer.getHeight() / 2 ) - event.getY()));
double angle = (int) Math.toDegrees(rotationAngleRadians);
Log.i("gg", "rotaion angle"+angle);*/
double currentAngle = getAngle(event.getX(), event.getY());
//if(currentAngle < 130 || currentAngle < 110){
//Log.e("Start angle :"+startAngle, "Current angle:"+currentAngle);
rotateDialer((float) (startAngle - currentAngle));
startAngle = currentAngle;
//}
//Log.e("MOVE start Degree:"+startAngle, "Current Degree :"+currentAngle);
break;
case MotionEvent.ACTION_UP:
//allowRotating = true;
break;
}
// set the touched quadrant to true
//quadrantTouched[getQuadrant(event.getX() - (dialerWidth / 2), dialerHeight - event.getY() - (dialerHeight / 2))] = true;
//detector.onTouchEvent(event);
return true;
}
}
I do not understand your problem. The code below rotate the image 48 degrees.
ImageView dialer = (ImageView) findViewById(R.id.imageView_ring);
int degrees = 48;
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
Bitmap bmpBowRotated = Bitmap.createBitmap(imageOrginal, 0, 0, imageOrginal.getWidth(),imageOrginal.getHeight(), matrix, false);
dialer.setImageBitmap(bmpBowRotated);
Hi Girish there is a class Named RotateAnimation by using this class u can easily do it
look Example like
RotateAnimation r = new RotateAnimation(0f, -90f,200,200); // HERE
r.setStartOffset(1000);
r.setDuration(1000);
r.setFillAfter(true); //HERE
animationSet.addAnimation(r);
I would like to first know what will be there for deployment? Does it allow manipulation Evenets? if yes then you get handle ManipulationStatring and ManipulationDelta Event to rotate the element.
If the same is not the case where Manipulation is not available then you can try RenderTransformation property with RorateTransform of the element is you are working with WPf.
I was able to achieve this by doing few of the following tweaks on your code
Making user click exactly on the arrow always to get the initial angle at which the arrow is placed, in your case 90 degree, else return false
Also save the angle at which the user removed his finger and use that angle as the initial value for his next touch ,like if he placed arrow at 100 deg make that his initial touch position to activate rotation again
Now for checking his answer take the angle at which your numbers 0 to 9 are placed ,im guessing your values take 120 deg from 0 to 9, divide that angle by 10, you can easily find out what angle represents what value and get your result
Also touching exactly at 90deg to begin rotation is very irritating, so always check for value which is bw 90+4 and 90-4 to begin, but always use the 90 as your start angle

Categories

Resources