玩过LOL的人都知道,里面的英雄蛮子的5秒真男人,所以本篇文章也不会太长。。。先贴一个早上司机群里看到的搞笑图片,图片来源于夜神,有需要的可以私信他。。。
俗话说得好中午不睡下午崩溃,在这个喜大普奔的日子,我也有和大多数单身狗一样,有一个共同的想法(一大早就被喂了半年的狗粮,我的内心毫无波动,甚至想笑):白天卖花,晚上卖套。。。
抱歉今天出门没吃药,扯了半天还没说到正题。今天要写的内容呢,是一个圆形旋转的效果(渣渣表示写一个效果用了丧心病狂的半天时间),国际惯例效果图先行,请看图
本来我之前是做成的点击图片然后获取rgb,但是产品要求要能滑动,好吧做为一个有节操的程序猿,勉为其难写一个效果吧(其实我内心是拒绝的)。具体效果要求是圆环可以旋转,当手指离开的时候要获取指针棒指向图片的位置的rgb值(圆环是图片给的一张整图)。所以呢要解决的问题就2个:
- 指针的位置坐标相对于圆盘图片所在的坐标值;根据坐标值获取图片的rgb值
让圆环转动
先看最主要的问题怎么让圆盘转动呢,你可以用
canvas.rotate(angle, mCenterX, mCenterY)
实现转动,要怎么跟随手指转动呢,这个要借用一下高中的数学姿势,由于我高中数学是体育老师教的下面方法我说得不好,不要打我。
先画一个草图讲解一下
第一步我们先算down下时候的角度值,然后move时候的角度值相减得到角度差值,用角度差值去旋转画布。看下怎么计算角度值呢
/**
* @return The angle of the unit circle with the image views center
*/
private double getPositionAngle(double xTouch, double yTouch) {
double x = xTouch - mCenterX;
double y = mHeight - yTouch - mCenterY;
switch (getPositionQuadrant(x, y)) {
case 1:
return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
case 2:
case 3:
return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
case 4:
return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
default:
// ignore, does not happen
return 0;
}
}
/**
* @return The quadrant of the position
*/
private static int getPositionQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
下面是重点….很简单先获取象限,然后根据象限获取到弧度值,在把弧度值转换为角度值。获取象限值getPositionQuadrant
都应能够看懂,获取角度值的时候有点小问题。数学里面定义的弧度值第一象限是0- π/2,是从x轴开始然后逆时针旋转的值。那么先看1象限的时候:Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
没问题,然后2象限的时候180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
由于是要从x轴开始然后逆时针旋转的值,asin是正值减去一个正值没错;然后2象限的时候180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
由于是要从x轴开始然后逆时针旋转的值,asin是负值减去一个负值没错(相当于是180+一个正值);然后4象限的时候360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
由于是要从x轴开始然后逆时针旋转的值,asin是负值加上一个负值没错(相当于360-一个正值)。当然了你可能也注意到了角度的差值是用的touchStartAngle - currentAngle
,因为Canvas
旋转是相对于x轴进行顺时针旋转….
至于怎么计算指针棒在圆环对应的位置就不详细讲了,看了代码都应该能够明白
先看RotateView
package com.pd.plugin.pd.led.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.Toast;
/**
* 详情参考 https://github.com/szugyi/Android-CircleMenu/blob/master/circlemenu/src/main/java/com/szugyi/circlemenu/view/CircleLayout.java
* Created by Tangxb on 2016/8/8.
*/
public class RotateView extends ImageView {
private int mWidth;
private int mHeight;
private float mRadius;
private float mCenterX;
private float mCenterY;
private float angle;
// Touch helpers
private double touchStartAngle;
private boolean didMove = false;
private int pointX;
private int pointY;
public RotateView(Context context) {
this(context, null);
}
public RotateView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RotateView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RotateView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mRadius = Math.min(w, h) / 2F;
mCenterX = mWidth / 2F;
mCenterY = mHeight / 2F;
}
public void setNeedPoint(int x, int y) {
pointX = x;
pointY = y;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
touchStartAngle = getPositionAngle(event.getX(), event.getY());
didMove = false;
break;
case MotionEvent.ACTION_MOVE:
double currentAngle = getPositionAngle(event.getX(), event.getY());
rotateButtons((float) (touchStartAngle - currentAngle));
touchStartAngle = currentAngle;
didMove = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (didMove) {
rotateViewToCenter();
}
break;
}
return true;
}
public void rotateViewToCenter() {
if (pointX == 0) return;
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
Bitmap srcBitmap = drawable.getBitmap();
Matrix matrix = new Matrix();
matrix.postRotate(angle, mCenterX, mCenterY);
Bitmap tempBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, false);
int color = tempBitmap.getPixel(pointX, pointY);
// 如果你想做的更细致的话 可以把颜色值的R G B 拿到做响应的处理
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
Toast.makeText(getContext(), "r=" + r + ",g=" + g + ",b=" + b, Toast.LENGTH_SHORT).show();
}
private void rotateButtons(float degrees) {
angle += degrees;
invalidate();
}
/**
* @return The angle of the unit circle with the image views center
*/
private double getPositionAngle(double xTouch, double yTouch) {
double x = xTouch - mCenterX;
double y = mHeight - yTouch - mCenterY;
switch (getPositionQuadrant(x, y)) {
case 1:
return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
case 2:
case 3:
return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
case 4:
return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
default:
// ignore, does not happen
return 0;
}
}
/**
* @return The quadrant of the position
*/
private static int getPositionQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.rotate(angle, mCenterX, mCenterY);
super.onDraw(canvas);
}
}
下面是计算指针位置TestFuckActivity
:
package com.pd.plugin.pd.led.activity;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.Display;
import android.widget.ImageView;
import com.pd.plugin.pd.led.R;
import com.pd.plugin.pd.led.view.RotateView;
/**
* Created by Tangxb on 2016/8/8.
*/
public class TestFuckActivity extends BaseActivity {
private RotateView imageView1;
private ImageView imageView2;
private int mScreenWidth;
private Handler mHandler = new Handler();
@Override
public int getLayoutResId() {
return R.layout.layout_fragment_play_three_part02;
}
@Override
protected void initView() {
imageView1 = getViewById(R.id.iv_color_palette);
imageView2 = getViewById(R.id.needle);
}
@Override
protected void initData() {
Display defaultDisplay = getWindowManager().getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
defaultDisplay.getMetrics(displayMetrics);
mScreenWidth = displayMetrics.widthPixels;
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
int[] location1 = new int[2];
int[] location2 = new int[2];
imageView1.getLocationInWindow(location1);
imageView2.getLocationInWindow(location2);
int x2 = location2[0];
int y2 = location2[1];
int y = y2 + imageView2.getHeight() / 2;
int x = 0;
if (x2 > mScreenWidth / 2) {
x = imageView2.getWidth() / 2 - location1[0];
} else {
x = imageView1.getWidth() / 2 + x2 - mScreenWidth / 2;
}
imageView1.setNeedPoint(x, y);
}
}, 200);
}
}
至于里面的圆环旋转加速度之类的暂时考虑。。。。