Android切换按钮拖动单击/拖动

时间:2014-10-27 14:17:50

标签: android uibutton uiswitch

我有一些关于Android切换按钮和创建一些自定义行为的具体问题。所以......我需要的是只允许开关在从OFF位置转换到ON位置时可以拖动。我能够得到它,如果我在关闭位置时单击开关,它将不会转换。但是,我不希望能够将开关从关闭位置转移到开启位置。我希望用户不得不经常拖动它。现在你可能会认为寻找条是我正在寻找的。也许,但是我需要拇指部分上的文本转换在进行切换时从关闭变为开启。使用Seek Bar时,这看起来并不是一个真正的选择。此外,如果用户在打开位置时单击拇指,则可以转换到关闭位置。而且,两者之间没有。如果用户从关闭开始(仅拖动),他们必须一直走到最后。任何帮助表示赞赏。我的基本代码如下:

public class MainActivity extends Activity {

    private TextView switchStatus;


private Switch mySwitch;

 private Handler handler = new Handler();

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  switchStatus = (TextView) findViewById(R.id.switchStatus);
  mySwitch = (Switch) findViewById(R.id.mySwitch);

  //set the switch to ON 
  mySwitch.setChecked(true);
  //attach a listener to check for changes in state
  mySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {

   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {

    if(isChecked){
     switchStatus.setText("Switch is currently ON");
    }else{
     switchStatus.setText("Switch is currently OFF");
    }

   }
  });

  mySwitch.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(mySwitch.isChecked()) {
            mySwitch.setChecked(false);
        }
    }   
  }); 

  //check the current state before we display the screen
  if(mySwitch.isChecked()){
   switchStatus.setText("Switch is currently ON");
  }
  else {
   switchStatus.setText("Switch is currently OFF");
  }
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

}

1 个答案:

答案 0 :(得分:1)

嗯,我找到了一个不是最优雅的解决方案,但我的工作。我扩展了开关控件并为想要对某些拖动事件起作用的对象创建了一个接口。请参阅下文。

public class CustomSwitch extends Switch {

   private static final String TAG = CustomSwitch.class.getSimpleName();

   private Method getThumbScrollRange;

   private int thumbScrollRange;
   private float thumbPosition;

   private boolean isMiddleOn = false;
   private boolean isMiddleOff = true;
   private boolean isOnMax = false;
   private boolean isOffMin = true;
   private boolean isMoving = false;

   private final int PIVOT_PERCENT = 50;
   private final int OFF_PERCENT_TOLERANCE = 10;
   private final int ON_PERCENT_TOLERANCE = 10;
   private final int ON_MAX_PERCENT = 100;
   private final int OFF_MIN_PERCENT = 0;

   private onDraggableSwitchListener onDraggableSwitchListener;

   public CustomSwitch(Context context) {
      this(context, null);
   }

   public CustomSwitch(Context context, AttributeSet attrs) {
      this(context, attrs, 0);
   }

   public CustomSwitch(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs);

      this.setOnTouchListener(new OnTouchListener() {
         // set via variable since the switch will trigger a move
         // action on toggle, but the on draw event will trigger
         @Override
         public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_MOVE) {
               isMoving = true;
            }
            else {
               isMoving = false;
            }
            if (onDraggableSwitchListener != null) {
               onDraggableSwitchListener.onTouchEvent(v, event);
            }
            return false;
         }
      });

      this.setOnCheckedChangeListener(new OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            isOnMax = isMiddleOn = isChecked;
            isOffMin = isMiddleOff = !isChecked;

            if (onDraggableSwitchListener != null) {
               onDraggableSwitchListener.onCheckedChanged(buttonView, isChecked);
            }
         }
      });

      try {
         getThumbScrollRange = Switch.class.getDeclaredMethod("getThumbScrollRange");
         getThumbScrollRange.setAccessible(true);
      }
      catch (NoSuchMethodException e) {
         Log.e(TAG, "Error", e);
      }
   }

   /**
    * Registers the {@link on}
    * */
   public void setOnDraggableSwitchListener(onDraggableSwitchListener listener) {
      onDraggableSwitchListener = listener;
   }

   @Override
   public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      try {
         thumbScrollRange = (Integer) getThumbScrollRange.invoke(this);
      }
      catch (Exception e) {
         Log.e(TAG, "", e);
      }
   }

   @Override
   protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      try {
         thumbPosition = getField("mThumbPosition").getFloat(this);
         int percentage = (thumbScrollRange == 0 ? 0 : ((int) ((thumbPosition / thumbScrollRange) * 100)));

         Log.v(TAG, "Percentage: " + percentage);

         if ((percentage > PIVOT_PERCENT) && !isMiddleOn && isMoving) {
            if (onDraggableSwitchListener != null) onDraggableSwitchListener.onDraggableSwitchOnMiddle(percentage);
            isMiddleOn = true;
            isOffMin = isMiddleOff = false;
            Log.v(TAG, "MIDDLE ON TRUE");
         }
         else if ((percentage < PIVOT_PERCENT) && !isMiddleOff && isMoving) {
            if (onDraggableSwitchListener != null) onDraggableSwitchListener.onDraggableSwitchOffMiddle(percentage);
            isMiddleOff = true;
            isOnMax = isMiddleOn = false;
            Log.v(TAG, "MIDDLE OFF TRUE");
         }

         if ((percentage <= (OFF_MIN_PERCENT + OFF_PERCENT_TOLERANCE)) && !isOffMin && isMoving) {
            if (onDraggableSwitchListener != null) onDraggableSwitchListener.onDraggableSwitchOffMin();
            isOffMin = true;
            Log.v(TAG, "OFF MIN TRUE");
         }
         else if ((percentage >= (ON_MAX_PERCENT - ON_PERCENT_TOLERANCE)) && !isOnMax && isMoving) {
            if (onDraggableSwitchListener != null) onDraggableSwitchListener.onDraggableSwitchOnMax();
            isOnMax = true;
            Log.v(TAG, "ON MAX TRUE");
         }
      }
      catch (IllegalArgumentException e) {
         Log.e(TAG, "", e);
      }
      catch (IllegalAccessException e) {
         Log.e(TAG, "", e);
      }
   }

   /** Cache of private fields from superclass */
   private Map<String, Field> fieldCache = new HashMap<String, Field>();

   private Field getField(String name) {

      try {
         if (!fieldCache.containsKey(name)) {
            Field f = Switch.class.getDeclaredField(name);
            f.setAccessible(true);
            fieldCache.put(name, f);
         }
         return fieldCache.get(name);
      }
      catch (Exception e) {
         throw new RuntimeException(e);
      }
   }

   public static interface onDraggableSwitchListener {

      public void onDraggableSwitchOnMax();

      public void onDraggableSwitchOffMin();

      public void onDraggableSwitchOnMiddle(int percentage);

      public void onDraggableSwitchOffMiddle(int percentage);

      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked);

      public void onTouchEvent(View v, MotionEvent event);
   }
}

您现在要做的就是在布局中使用此开关,然后在主类中设置适当的侦听器。希望这有助于某人(即使它非常具体)。