我想围绕他的中心旋转图片(ImageView中的位图)。 通过使用preRotate方法和Bitmap的值width / 2和height / 2以及1或-1度作为旋转因子,这非常有效。
但是我将旋转功能实现为按钮。每次按下“向右旋转”按钮时,Imageview会向右旋转一度,依此类推。按下按钮会很不错,按下按钮时图片开始旋转,直到按钮被释放。
我在这里阅读了一些线程,其中这些功能实现为OnTouchListener而不是OnClickListener,但它对我不起作用。如果我在MotionEvent.ACTION_DOWN事件中实现循环,那么它们是无限的。如果我不使用循环,那么事件只处理一次(如在OnClickListener中)。
那么在按下按钮时如何递增/递减旋转因子?
答案 0 :(得分:9)
简短回答:您需要实现相应的MotionEvent.ACTION_UP来停止添加。当用户按下时,ACTION_DOWN只被触发一次。这就是为什么当你没有循环时,你只有一个增量。你需要的是一个单独的线程,当MotionEvent.ACTION_DOWN完成时开始进行增量,并在触发MotionEvent.ACTION_UP时停止它们。这样的事情应该有效。
public MyActivity extends Activity{
private bool continueIncrementing;
private Runnable incrementerThread;
//put this OnTouchListener on your button
View.OnTouchListener downListener = new View.OnTouchListner(){
public onTouch(View v, MotionEvent event){
if(event == MotionEvent.ACTION_DOWN){
startIncrmenting();
}
else if(event == MotionEvent.ACTION_UP){
stopIncrementing();
}
}
};
private void startIncrmenting(){
setIsIncrementing(true);
new Thread(new Runnable() {
public void run() {
while(isIncrementing()){
//do incrementing in here
}
}
}).start();
}
sychronized private void stopIncrmenting(){
setIsIncrementing(false);
}
sychronized private bool isIncrmenting(){
return continueIncrementing;
}
synhronized void setIsIncrmenting(bool newSetting){
continueIncrementing = newSetting;
}
//rest of your activity
}
答案 1 :(得分:8)
我已将Knickedi的答案扩展到一个更通用的案例。希望有所帮助。
import android.view.MotionEvent;
import android.view.View;
public abstract class OnTouchContinuousListener implements View.OnTouchListener {
private final int mInitialRepeatDelay;
private final int mNormalRepeatDelay;
private View mView;
/**
* Construct listener with default delays
*/
public OnTouchContinuousListener() {
this.mInitialRepeatDelay = 500;
this.mNormalRepeatDelay = 200;
}
/**
*
* Construct listener with configurable delays
*
*
* @param initialRepeatDelay
* delay to the first repeat in millis
* @param normalRepeatDelay
* delay to subsequent repeats in millis
*/
public OnTouchContinuousListener(int initialRepeatDelay, int normalRepeatDelay) {
this.mInitialRepeatDelay = initialRepeatDelay;
this.mNormalRepeatDelay = normalRepeatDelay;
}
private final Runnable repeatRunnable = new Runnable() {
@Override
public void run() {
// as long the button is press we continue to repeat
if (mView.isPressed()) {
// Fire the onTouchRepeat event
onTouchRepeat(mView);
// Schedule the repeat
mView.postDelayed(repeatRunnable, mNormalRepeatDelay);
}
}
};
/**
* Called when a touch event is dispatched to a view. This allows listeners to
* get a chance to respond before the target view.
*
* @param v
* The view the touch event has been dispatched to.
* @param event
* The MotionEvent object containing full information about the
* event.
* @return True if the listener has consumed the event, false otherwise.
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mView = v;
// Fire the first touch straight away
onTouchRepeat(mView);
// Start the incrementing with the initial delay
mView.postDelayed(repeatRunnable, mInitialRepeatDelay);
}
// don't return true, we don't want to disable buttons default behavior
return false;
}
/**
* Called when the target item should be changed due to continuous touch. This
* happens at first press, and also after each repeat timeout. Releasing the
* touch will stop the repeating.
*
*/
public abstract void onTouchRepeat(View view);
}
答案 2 :(得分:2)
假设button
是私有成员,因此您可以在runnable成员中访问它。这就是我想要的。您可以考虑使用System.currentTimeMillis()
进行精确和基于时间的旋转值计算。
这是一个想法(谨慎,未经IDE测试和编写):
private Runnable rotationRunnable = new Runnable() {
@Override
public void run() {
// perform rotation step here
// as long the button is press we fire the rotation again
if (button.isPressed()) {
button.postDelayed(rotationRunnable, 40);
}
}
};
// in onCreate
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// inital start of rotation
v.post(rotationRunnable);
}
// don't return ture, we don't want to disable buttons default behavior
return false;
}
});