Android 如何在特定角度暂停画布旋转2秒?
我做了一个旋转旋钮,但我想在特定角度停止旋钮2秒钟。我想停在260f和-20f 有人能建议怎么做吗 这是来自博客的代码。我根据我的要求做了很多改变Android 如何在特定角度暂停画布旋转2秒?,android,math,layout,view,rotation,Android,Math,Layout,View,Rotation,我做了一个旋转旋钮,但我想在特定角度停止旋钮2秒钟。我想停在260f和-20f 有人能建议怎么做吗 这是来自博客的代码。我根据我的要求做了很多改变 public class RotatoryKnobView extends ImageView { private float angle = -20f; private float theta_old=0f; private RotaryKnobListener listener; public interface Rota
public class RotatoryKnobView extends ImageView {
private float angle = -20f;
private float theta_old=0f;
private RotaryKnobListener listener;
public interface RotaryKnobListener {
public void onKnobChanged(float arg);
}
public void setKnobListener(RotaryKnobListener l )
{
listener = l;
}
public RotatoryKnobView(Context context) {
super(context);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initialize();
}
private float getTheta(float x, float y)
{
float sx = x - (getWidth() / 2.0f);
float sy = y - (getHeight() / 2.0f);
float length = (float)Math.sqrt( sx*sx + sy*sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float)Math.atan2( ny, nx );
final float rad2deg = (float)(180.0/Math.PI);
float thetaDeg = theta*rad2deg;
return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg;
}
public void initialize()
{
this.setImageResource(R.drawable.rotoron);
setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX(0);
float y = event.getY(0);
float theta = getTheta(x,y);
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN:
theta_old = theta;
break;
case MotionEvent.ACTION_MOVE:
invalidate();
float delta_theta = theta - theta_old;
theta_old = theta;
int direction = (delta_theta > 0) ? 1 : -1;
angle += 5*direction;
notifyListener(angle+20);
break;
}
return true;
}
});
}
private void notifyListener(float arg)
{
if (null!=listener)
listener.onKnobChanged(arg);
}
protected void onDraw(Canvas c)
{if(angle==257f){
try {
synchronized (c) {
c.wait(5000);
angle=260f;
}
} catch (InterruptedException e) {
}
}
else if(angle==-16f)
{
try {
synchronized (c) {
c.wait(5000);
angle=-20f;
}
} catch (InterruptedException e) {
}
}
else
if(angle>260f)
{
angle=-20f;
}
else if(angle<-20f)
{
angle=260f;
}
else{
c.rotate(angle,getWidth()/2,getHeight()/2);
}
super.onDraw(c);
}
}
公共类RotatoryKnobView扩展了ImageView{
专用浮动角度=-20f;
私有浮点θ_old=0f;
私人RotaryKnobListener监听器;
公共接口RotaryKnobListener{
更改后的公共无效(浮动参数);
}
公共无效设置Knoblistener(RotaryKnobListener l)
{
监听器=l;
}
公共旋转KnobView(上下文){
超级(上下文);
初始化();
}
公共旋转KnobView(上下文、属性集属性)
{
超级(上下文,attrs);
初始化();
}
公共旋转KnobView(上下文上下文、属性集属性、int-defStyle)
{
超级(上下文、属性、定义样式);
初始化();
}
私有浮点getTheta(浮点x,浮点y)
{
浮点sx=x-(getWidth()/2.0f);
float sy=y-(getHeight()/2.0f);
浮点长度=(浮点)数学sqrt(sx*sx+sy*sy);
浮动nx=sx/长度;
浮动ny=sy/长度;
浮点θ=(浮点)数学atan2(ny,nx);
最终浮点数rad2deg=(浮点数)(180.0/Math.PI);
浮点数θ=θ*rad2deg;
返回(标记<0)?标记+360.0f:标记;
}
公共无效初始化()
{
这个.setImageResource(R.drawable.rotoron);
setOnTouchListener(新的OnTouchListener()
{
@凌驾
公共布尔onTouch(视图v,运动事件){
float x=event.getX(0);
float y=event.getY(0);
浮点θ=getTheta(x,y);
开关(event.getAction()&MotionEvent.ACTION\u掩码)
{
case MotionEvent.ACTION\u指针\u向下:
θ=θ;
打破
case MotionEvent.ACTION\u移动:
使无效();
浮动增量θ=θ-θ旧;
θ=θ;
int方向=(δθ>0)?1:-1;
角度+=5*方向;
(角度+20);
打破
}
返回true;
}
});
}
私有void notifyListener(浮点参数)
{
if(null!=侦听器)
onKnobChanged(arg);
}
受保护的void onDraw(画布c)
{如果(角度==257f){
试一试{
已同步(c){
c、 等待(5000);
角度=260f;
}
}捕捉(中断异常e){
}
}
否则如果(角度==-16f)
{
试一试{
已同步(c){
c、 等待(5000);
角度=-20f;
}
}捕捉(中断异常e){
}
}
其他的
如果(角度>260f)
{
角度=-20f;
}
else if(angle我认为这里的最终答案是通过扩展SurfaceView
然后重写onDraw
(Canvas)来实现您自己的类
然后可以使用画布例程呈现控件
如果你用谷歌搜索,有很多好的例子
要开始初始化曲面视图,请执行以下操作:
// So things actually render
setDrawingCacheEnabled(true);
setWillNotDraw(false);
setZOrderOnTop(true);
// Controls the drawing thread.
getHolder().addCallback(new CallbackSurfaceView());
覆盖onDraw并添加渲染例程。您可以将它们分层
随你去
public void onDraw(Canvas canvas) {
// Always Draw
super.onDraw(canvas);
drawBackground(canvas);
drawKnobIndentWell(canvas);
drawKnob(canvas);
drawKnobLED( canvas ); //etc....
}
回调和更新线程的示例:
/**
* This is the drawing callback.
* It handles the creation and destruction of the drawing thread when the
* surface for drawing is created and destroyed.
*/
class CallbackSurfaceView implements SurfaceHolder.Callback {
Thread threadIndeterminant;
RunnableProgressUpdater runnableUpdater;
boolean done = false;
/**
* Kills the running thread.
*/
public void done() {
done = true;
if (null != runnableUpdater) {
runnableUpdater.done();
}
}
/**
* Causes the UI to render once.
*/
public void needRedraw() {
if (runnableUpdater != null) {
runnableUpdater.needRedraw();
}
}
/**
* When the surface is created start the drawing thread.
* @param holder
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!done) {
threadIndeterminant = new Thread(runnableUpdater = new RunnableProgressUpdater());
threadIndeterminant.start();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/**
* When the surface is destroyed stop the drawing thread.
* @param holder
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (null != runnableUpdater) {
runnableUpdater.done();
threadIndeterminant = null;
runnableUpdater = null;
}
}
}
/**
* This is the runnable for the drawing operations. It is started and stopped by the callback class.
*/
class RunnableProgressUpdater implements Runnable {
boolean surfaceExists = true;
boolean needRedraw = false;
public void done() {
surfaceExists = false;
}
public void needRedraw() {
needRedraw = true;
}
@Override
public void run() {
canvasDrawAndPost();
while (surfaceExists) {
// Renders continuously during a download operation.
// Otherwise only renders when requested.
// Necessary so that progress bar and cirlce activity update.
if (syncContext.isRunning()) {
canvasDrawAndPost();
needRedraw = true;
} else if (needRedraw) {
canvasDrawAndPost();
needRedraw = false;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// Don't care
}
}
// One final update
canvasDrawAndPost();
}
/**
* Routine the redraws the controls on each loop.
*/
private synchronized void canvasDrawAndPost() {
Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
try {
draw(canvas);
} finally {
getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
如果您决定走这条路,您可以使用XML自定义控件
自定义值
<com.killerknob.graphics.MultimeterVolumeControl
android:id="@+id/volume_control"
android:layout_below="@id/divider_one"
android:background="@android:color/white"
android:layout_width="match_parent"
android:layout_height="60dp"
android:minHeight="60dp"
custom:ledShadow="#357BBB"
custom:ledColor="#357BBB"
custom:knobBackground="@color/gray_level_13"
custom:knobColor="@android:color/black"
/>
创建自定义控件时,可以通过其包名引用它。
您可以在/values下的资源文件中创建自定义变量,然后引用
他们在你们班上
详情如下:
这可能是更多的工作,然后你想做的,但我认为你最终会有一个更专业的外观控制和动画将更加顺利
无论如何,这看起来是一个有趣的项目。祝你好运。你可以设置一个固定角度,并在2秒后使用postDelayed清除它
public class RotatoryKnobView extends ImageView {
private float angle = -20f;
private float theta_old=0f;
private RotaryKnobListener listener;
private Float fixedAngle;
private float settleAngle;
private Runnable unsetFixedAngle = new Runnable() {
@Override
public void run() {
angle = settleAngle;
fixedAngle = null;
invalidate();
}
};
public interface RotaryKnobListener {
public void onKnobChanged(float arg);
}
public void setKnobListener(RotaryKnobListener l )
{
listener = l;
}
public RotatoryKnobView(Context context) {
super(context);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public RotatoryKnobView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initialize();
}
private float getTheta(float x, float y)
{
float sx = x - (getWidth() / 2.0f);
float sy = y - (getHeight() / 2.0f);
float length = (float)Math.sqrt( sx*sx + sy*sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float)Math.atan2( ny, nx );
final float rad2deg = (float)(180.0/Math.PI);
float thetaDeg = theta*rad2deg;
return (thetaDeg < 0) ? thetaDeg + 360.0f : thetaDeg;
}
public void initialize()
{
this.setImageResource(R.drawable.rotoron);
setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX(0);
float y = event.getY(0);
float theta = getTheta(x,y);
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_POINTER_DOWN:
theta_old = theta;
break;
case MotionEvent.ACTION_MOVE:
invalidate();
float delta_theta = theta - theta_old;
theta_old = theta;
int direction = (delta_theta > 0) ? 1 : -1;
angle += 5*direction;
notifyListener(angle+20);
break;
}
return true;
}
});
}
private void notifyListener(float arg)
{
if (null!=listener)
listener.onKnobChanged(arg);
}
void setFixedAngle(float angle, float settleAngle) {
fixedAngle = angle;
this.settleAngle = settleAngle;
postDelayed(unsetFixedAngle, 2000);
}
protected void onDraw(Canvas c)
{
if(fixedAngle==null) {
if (angle > 270) {
setFixedAngle(270, -15);
} else if (angle < -20f) {
setFixedAngle(-20, 260);
}
}
Log.d("angle", "angle: " + angle + " fixed angle: " + fixedAngle);
c.rotate(fixedAngle == null ? angle : fixedAngle,getWidth()/2,getHeight()/2);
super.onDraw(c);
}
}
公共类RotatoryKnobView扩展了ImageView{
专用浮动角度=-20f;
私有浮点θ_old=0f;
私人RotaryKnobListener监听器;
私人浮动固定角;
私人浮动结算;
private Runnable unfixedangle=new Runnable(){
@凌驾
公开募捐{
角度=沉降角;
fixedAngle=null;
使无效();
}
};
公共接口RotaryKnobListener{
更改后的公共无效(浮动参数);
}
公共无效设置Knoblistener(RotaryKnobListener l)
{
监听器=l;
}
公共旋转KnobView(上下文){
超级(上下文);
初始化();
}
公共旋转KnobView(上下文、属性集属性)
{
超级(上下文,attrs);
初始化();
}
公共旋转KnobView(上下文上下文、属性集属性、int-defStyle)
{
超级(上下文、属性、定义样式);
初始化();
}
私有浮点getTheta(浮点x,浮点y)
{
浮点sx=x-(getWidth()/2.0f);
float sy=y-(getHeight()/2.0f);
浮点长度=(浮点)数学sqrt(sx*sx+sy*sy);
浮动nx=sx/长度;
浮动ny=sy/长度;
浮点θ=(浮点)数学atan2(ny,nx);
最终浮点数rad2deg=(浮点数)(180.0/Math.PI);
浮点数θ=θ*rad2deg;
返回(标记<0)?标记+360.0f:标记;
}
公共无效初始化()
{
这个.setImageResource(R.drawable.rotoron);
setOnTouchListener(新的OnTouchListener()
{
@凌驾
公共布尔onTouch(视图v,运动事件){
float x=event.getX(0);
float y=event.getY(0);
浮点θ=getTheta(x,y);
开关(event.getAction()&MotionEvent.ACTION\u掩码)
{
case MotionEvent.ACTION\u指针\u向下:
θ=θ;
打破
case MotionEvent.ACTION\u移动: