解决方案 »

  1.   

    你的layout文件还有MySlipSwitch代码
      

  2.   

    回帖记得引用,不然别人根本不知道你回复就是贴了哪些代码才知道哪的问题,你这估计是解析布局 switch_on_Bkg为null了,所以才提示空指针,不过运行起来应该是没问题的
      

  3.   

    回帖记得引用,不然别人根本不知道你回复就是贴了哪些代码才知道哪的问题,你这估计是解析布局 switch_on_Bkg为null了,所以才提示空指针,不过运行起来应该是没问题的好的,记住了
    public class MySlipSwitch extends View implements OnTouchListener { // 开关开启时的背景,关闭时的背景,滑动按钮
    private Bitmap switch_on_Bkg, switch_off_Bkg, slip_Btn;
    private Rect on_Rect, off_Rect; // 是否正在滑动
    private boolean isSlipping = false;
    // 当前开关状态,true为开启,false为关闭
    private boolean isSwitchOn = false; // 手指按下时的水平坐标X,当前的水平坐标X
    private float previousX, currentX = 80; // 开关监听器
    private OnSwitchListener onSwitchListener;
    // 是否设置了开关监听器
    private boolean isSwitchListenerOn = false; public MySlipSwitch(Context context) {
    super(context);
    init();
    } public MySlipSwitch(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
    } private void init() {
    setOnTouchListener(this);
    } protected void setImageResource(int switchOnBkg, int switchOffBkg,
    int slipBtn) {
    switch_on_Bkg = BitmapFactory.decodeResource(getResources(),
    switchOnBkg);
    switch_off_Bkg = BitmapFactory.decodeResource(getResources(),
    switchOffBkg);
    slip_Btn = BitmapFactory.decodeResource(getResources(), slipBtn); // 右半边Rect,即滑动按钮在右半边时表示开关开启
    on_Rect = new Rect(switch_off_Bkg.getWidth() - slip_Btn.getWidth(), 0,
    switch_off_Bkg.getWidth(), slip_Btn.getHeight());
    // 左半边Rect,即滑动按钮在左半边时表示开关关闭
    off_Rect = new Rect(0, 0, slip_Btn.getWidth(), slip_Btn.getHeight());
    } // 设置开关状态
    protected void setSwitchState(boolean switchState) {
    isSwitchOn = switchState;
    Log.e("========", "set");
    } // 获取开关状态
    protected boolean getSwitchState() {
    return isSwitchOn;
    } protected void updateSwitchState(boolean switchState) {
    isSwitchOn = switchState;
    Log.e("==========", "update");
    invalidate();
    } @Override
    protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas); Matrix matrix = new Matrix();
    Paint paint = new Paint();
    // 滑动按钮的左边坐标
    float left_SlipBtn; // 手指滑动到左半边的时候表示开关为关闭状态,滑动到右半边的时候表示开关为开启状态
    if (currentX < (switch_on_Bkg.getWidth() / 2)) {
    canvas.drawBitmap(switch_off_Bkg, matrix, paint);
    } else {
    canvas.drawBitmap(switch_on_Bkg, matrix, paint);
    } // 判断当前是否正在滑动
    if (isSlipping) {
    if (currentX > switch_on_Bkg.getWidth()) {
    Log.e("=========", "slip");
    left_SlipBtn = switch_on_Bkg.getWidth() - slip_Btn.getWidth();

    else {
    Log.e("=========", "slip");
    left_SlipBtn = currentX - slip_Btn.getWidth() / 2; // 为什么是减1/2 } 
    }
    else {
    // 根据当前的开关状态设置滑动按钮的位置
    if (isSwitchOn) {
    Log.e("isSwitchOn", isSwitchOn + "");
    Log.e("currentX", currentX + "");
    Log.e("=========", "on");
    left_SlipBtn = on_Rect.left;
    } else {
    Log.e("=========", "off");
    left_SlipBtn = off_Rect.left;
    }
    } // 对滑动按钮的位置进行异常判断
    if (left_SlipBtn < 0) {
    left_SlipBtn = 0;
    } else if (left_SlipBtn > switch_on_Bkg.getWidth()- slip_Btn.getWidth()) {
    left_SlipBtn = switch_on_Bkg.getWidth() - slip_Btn.getWidth();
    }
    Log.e("left_SlipBtn", left_SlipBtn + "");
    canvas.drawBitmap(slip_Btn, left_SlipBtn, 0, paint);
    } @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    Log.e("widthMeasureSpec", widthMeasureSpec + "");
    Log.e("heightMeasureSpec", heightMeasureSpec + "");
    setMeasuredDimension(switch_on_Bkg.getWidth(),
    switch_on_Bkg.getHeight());
    Log.e("switch_on_Bkg", switch_on_Bkg.getWidth() + "");
    Log.e("switch_on_Bkg", switch_on_Bkg.getHeight() + "");
    } @Override
    public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub
    switch (event.getAction()) {
    // 滑动
    case MotionEvent.ACTION_MOVE:
    Log.e("===========", "move");
    currentX = event.getX();
    break; // 按下
    case MotionEvent.ACTION_DOWN:
    if (event.getX() > switch_on_Bkg.getWidth()
    || event.getY() > switch_on_Bkg.getHeight()) {
    return false;
    }
    Log.e("===========", "down");
    isSlipping = true;
    previousX = event.getX();
    currentX = previousX;
    break; // 松开
    case MotionEvent.ACTION_UP:
    isSlipping = false;
    // 松开前开关的状态
    Log.e("============", "up");
    boolean previousSwitchState = isSwitchOn; if (event.getX() >= (switch_on_Bkg.getWidth() / 2)) {
    isSwitchOn = true;
    } else {
    isSwitchOn = false;
    } // 如果设置了监听器,则调用此方法
    if (isSwitchListenerOn && (previousSwitchState != isSwitchOn)) {
    onSwitchListener.onSwitched(isSwitchOn);
    }
    break; default:
    break;
    } // 重新绘制控件
    invalidate();
    return true;
    } public void setOnSwitchListener(OnSwitchListener listener) {
    onSwitchListener = listener;
    isSwitchListenerOn = true;
    } public interface OnSwitchListener {
    abstract void onSwitched(boolean isSwitchOn);
    }
    }上面是实现功能的代码,有几个问题希望能帮忙解答。
    1、在判断是否滑动时,left_SlipBtn = currentX - slip_Btn.getWidth() / 2;为什么减去游标的1/2
    2、实际效果游标和背景边缘有间距,边缘为什么不重合
      

  4.   


    回帖记得引用,不然别人根本不知道你回复就是贴了哪些代码才知道哪的问题,你这估计是解析布局 switch_on_Bkg为null了,所以才提示空指针,不过运行起来应该是没问题的
    能帮我看下另一个问题吗
    public class MySlipSwitch extends View implements OnTouchListener { // 开关开启时的背景,关闭时的背景,滑动按钮
    private Bitmap switch_on_Bkg, switch_off_Bkg, slip_Btn;
    private Rect on_Rect, off_Rect; // 是否正在滑动
    private boolean isSlipping = false;
    // 当前开关状态,true为开启,false为关闭
    private boolean isSwitchOn = false; // 手指按下时的水平坐标X,当前的水平坐标X
    private float previousX, currentX = 80; // 开关监听器
    private OnSwitchListener onSwitchListener;
    // 是否设置了开关监听器
    private boolean isSwitchListenerOn = false; public MySlipSwitch(Context context) {
    super(context);
    init();
    } public MySlipSwitch(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
    } private void init() {
    setOnTouchListener(this);
    } protected void setImageResource(int switchOnBkg, int switchOffBkg,
    int slipBtn) {
    switch_on_Bkg = BitmapFactory.decodeResource(getResources(),
    switchOnBkg);
    switch_off_Bkg = BitmapFactory.decodeResource(getResources(),
    switchOffBkg);
    slip_Btn = BitmapFactory.decodeResource(getResources(), slipBtn); // 右半边Rect,即滑动按钮在右半边时表示开关开启
    on_Rect = new Rect(switch_off_Bkg.getWidth() - slip_Btn.getWidth(), 0,
    switch_off_Bkg.getWidth(), slip_Btn.getHeight());
    // 左半边Rect,即滑动按钮在左半边时表示开关关闭
    off_Rect = new Rect(0, 0, slip_Btn.getWidth(), slip_Btn.getHeight());
    } // 设置开关状态
    protected void setSwitchState(boolean switchState) {
    isSwitchOn = switchState;
    Log.e("========", "set");
    } // 获取开关状态
    protected boolean getSwitchState() {
    return isSwitchOn;
    } protected void updateSwitchState(boolean switchState) {
    isSwitchOn = switchState;
    Log.e("==========", "update");
    invalidate();
    } @Override
    protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas); Matrix matrix = new Matrix();
    Paint paint = new Paint();
    // 滑动按钮的左边坐标
    float left_SlipBtn; // 手指滑动到左半边的时候表示开关为关闭状态,滑动到右半边的时候表示开关为开启状态
    if (currentX < (switch_on_Bkg.getWidth() / 2)) {
    canvas.drawBitmap(switch_off_Bkg, matrix, paint);
    } else {
    canvas.drawBitmap(switch_on_Bkg, matrix, paint);
    } // 判断当前是否正在滑动
    if (isSlipping) {
    if (currentX > switch_on_Bkg.getWidth()) {
    Log.e("=========", "slip");
    left_SlipBtn = switch_on_Bkg.getWidth() - slip_Btn.getWidth();

    else {
    Log.e("=========", "slip");
    left_SlipBtn = currentX - slip_Btn.getWidth() / 2; // 为什么是减1/2 } 
    }
    else {
    // 根据当前的开关状态设置滑动按钮的位置
    if (isSwitchOn) {
    Log.e("isSwitchOn", isSwitchOn + "");
    Log.e("currentX", currentX + "");
    Log.e("=========", "on");
    left_SlipBtn = on_Rect.left;
    } else {
    Log.e("=========", "off");
    left_SlipBtn = off_Rect.left;
    }
    } // 对滑动按钮的位置进行异常判断
    if (left_SlipBtn < 0) {
    left_SlipBtn = 0;
    } else if (left_SlipBtn > switch_on_Bkg.getWidth()- slip_Btn.getWidth()) {
    left_SlipBtn = switch_on_Bkg.getWidth() - slip_Btn.getWidth();
    }
    Log.e("left_SlipBtn", left_SlipBtn + "");
    canvas.drawBitmap(slip_Btn, left_SlipBtn, 0, paint);
    } @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    Log.e("widthMeasureSpec", widthMeasureSpec + "");
    Log.e("heightMeasureSpec", heightMeasureSpec + "");
    setMeasuredDimension(switch_on_Bkg.getWidth(),
    switch_on_Bkg.getHeight());
    Log.e("switch_on_Bkg", switch_on_Bkg.getWidth() + "");
    Log.e("switch_on_Bkg", switch_on_Bkg.getHeight() + "");
    } @Override
    public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub
    switch (event.getAction()) {
    // 滑动
    case MotionEvent.ACTION_MOVE:
    Log.e("===========", "move");
    currentX = event.getX();
    break; // 按下
    case MotionEvent.ACTION_DOWN:
    if (event.getX() > switch_on_Bkg.getWidth()
    || event.getY() > switch_on_Bkg.getHeight()) {
    return false;
    }
    Log.e("===========", "down");
    isSlipping = true;
    previousX = event.getX();
    currentX = previousX;
    break; // 松开
    case MotionEvent.ACTION_UP:
    isSlipping = false;
    // 松开前开关的状态
    Log.e("============", "up");
    boolean previousSwitchState = isSwitchOn; if (event.getX() >= (switch_on_Bkg.getWidth() / 2)) {
    isSwitchOn = true;
    } else {
    isSwitchOn = false;
    } // 如果设置了监听器,则调用此方法
    if (isSwitchListenerOn && (previousSwitchState != isSwitchOn)) {
    onSwitchListener.onSwitched(isSwitchOn);
    }
    break; default:
    break;
    } // 重新绘制控件
    invalidate();
    return true;
    } public void setOnSwitchListener(OnSwitchListener listener) {
    onSwitchListener = listener;
    isSwitchListenerOn = true;
    } public interface OnSwitchListener {
    abstract void onSwitched(boolean isSwitchOn);
    }
    }实际效果游标和背景边缘有间距,边缘为什么不重合
      

  5.   

    在构造函数中加句代码试试 if (isInEditMode()) { 
    return; 
    }