SlideSwitch开关带文字(有动画效果)

package cn.wanxue.gaokao.famous;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import cn.wanxue.gaokao.R;

/**

  • Created by LHX
  • on 2019/8/7
    */
    public class SlideSwitch extends View
    {
    public static final String TAG = “SlideSwitch”;
    public static final int SWITCH_OFF = 0;//关闭状态
    public static final int SWITCH_ON = 1;//打开状态
    public static final int SWITCH_SCROLING = 2;//滚动状态

//用于显示的文本
private String mOnText = “”;
private String mOffText = “”;

private int mSwitchStatus = SWITCH_ON;

private boolean mHasScrolled = false;//表示是否发生过滚动

private int mSrcX = 0, mDstX = 0;

private int mBmpWidth = 0;
private int mBmpHeight = 0;
private int mThumbWidth = 0;

private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

private OnSwitchChangedListener mOnSwitchChangedListener = null;

//开关状态图
Bitmap mSwitch_off, mSwitch_on, mSwitch_thumb;

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

public SlideSwitch(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}

public SlideSwitch(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}

//初始化三幅图片
private void init()
{
Resources res = getResources();
mSwitch_off = BitmapFactory.decodeResource(res, R.drawable.tuoyuan_lleft);
mSwitch_on = BitmapFactory.decodeResource(res, R.drawable.tuoyuan_right);
mSwitch_thumb = BitmapFactory.decodeResource(res, R.drawable.tuoyuan_circle);
mBmpWidth = mSwitch_on.getWidth();
mBmpHeight = mSwitch_on.getHeight();
mThumbWidth = mSwitch_thumb.getWidth();
}

@Override
public void setLayoutParams(ViewGroup.LayoutParams params)
{
params.width = mBmpWidth;
params.height = mBmpHeight;
super.setLayoutParams(params);
}

/**

  • 为开关控件设置状态改变监听函数
  • @param onSwitchChangedListener 参见 {@link OnSwitchChangedListener}
    */
    public void setOnSwitchChangedListener(OnSwitchChangedListener onSwitchChangedListener)
    {
    mOnSwitchChangedListener = onSwitchChangedListener;
    }

/**

  • 设置开关上面的文本
  • @param onText 控件打开时要显示的文本
  • @param offText 控件关闭时要显示的文本
    */
    public void setText(final String onText, final String offText)
    {
    mOnText = onText;
    mOffText =offText;
    invalidate();
    }

/**

  • 设置开关的状态
  • @param on 是否打开开关 打开为true 关闭为false
    */
    public void setStatus(boolean on)
    {
    mSwitchStatus = ( on ? SWITCH_OFF : SWITCH_ON);
    }

@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mSrcX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
mDstX = Math.max( (int) event.getX(), 10);
mDstX = Math.min( mDstX, 62);
if(mSrcX == mDstX)
return true;
mHasScrolled = true;
AnimationTransRunnable aTransRunnable = new AnimationTransRunnable(mSrcX, mDstX, 1);
new Thread(aTransRunnable).start();
mSrcX = mDstX;
break;
case MotionEvent.ACTION_UP:
if(mHasScrolled == false)//如果没有发生过滑动,就意味着这是一次单击过程
{
mSwitchStatus = Math.abs(mSwitchStatus-1);
int xFrom = 10, xTo = 62;
if(mSwitchStatus == SWITCH_OFF)
{
xFrom = 62;
xTo = 10;
}
AnimationTransRunnable runnable = new AnimationTransRunnable(xFrom, xTo, 1);
new Thread(runnable).start();
}
else
{
invalidate();
mHasScrolled = false;
}
//状态改变的时候 回调事件函数
if(mOnSwitchChangedListener != null)
{
mOnSwitchChangedListener.onSwitchChanged(this, mSwitchStatus);
}
break;

  default:
    break;
}
return true;

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//绘图的时候 内部用到了一些数值的硬编码,其实不太好,
//主要是考虑到图片的原因,图片周围有透明边界,所以要有一定的偏移
//硬编码的数值只要看懂了代码,其实可以理解其含义,可以做相应改进。
mPaint.setTextSize(20);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);

if(mSwitchStatus == SWITCH_OFF)
{
  drawBitmap(canvas, null, null, mSwitch_off);

  int count = canvas.save();
  canvas.translate(8, (mSwitch_on.getHeight()-mSwitch_thumb.getHeight())/2);
  drawBitmap(canvas, null, null, mSwitch_thumb);
  canvas.restoreToCount(count);

  mPaint.setColor(Color.rgb(105, 105, 105));
  canvas.drawText(mOffText, 0, 25, mPaint);
}
else if(mSwitchStatus == SWITCH_ON)
{
  drawBitmap(canvas, null, null, mSwitch_on);
  int count = canvas.save();
  canvas.translate(mSwitch_on.getWidth() - mSwitch_thumb.getWidth()-8, (mSwitch_on.getHeight()-mSwitch_thumb.getHeight())/2);
  drawBitmap(canvas, null, null, mSwitch_thumb);
  canvas.restoreToCount(count);

  mPaint.setColor(Color.rgb(105, 105, 105));
  canvas.drawText(mOnText, 17, 25, mPaint);
}
else //SWITCH_SCROLING
{
  mSwitchStatus = mDstX > 35 ? SWITCH_ON : SWITCH_OFF;
  drawBitmap(canvas, new Rect(0, 0, mDstX, mBmpHeight), new Rect(0, 0, (int)mDstX, mBmpHeight), mSwitch_on);
  mPaint.setColor(Color.WHITE);
  canvas.drawText(mOnText, 17, 20, mPaint);

  int count = canvas.save();
  canvas.translate(mDstX, 0);
  drawBitmap(canvas, new Rect(mDstX, 0, mBmpWidth, mBmpHeight),
    new Rect(0, 0, mBmpWidth - mDstX, mBmpHeight), mSwitch_off);
  canvas.restoreToCount(count);

  count = canvas.save();
  canvas.clipRect(mDstX, 0, mBmpWidth, mBmpHeight);
  canvas.translate(mThumbWidth, 0);
  mPaint.setColor(Color.rgb(105, 105, 105));
  canvas.drawText(mOffText, 0, 20, mPaint);
  canvas.restoreToCount(count);

  count = canvas.save();
  canvas.translate(mDstX - mThumbWidth / 2 +8, (mSwitch_off.getHeight()-mSwitch_thumb.getHeight())/2);
  drawBitmap(canvas, null, null, mSwitch_thumb);
  canvas.restoreToCount(count);
}

}

public void drawBitmap(Canvas canvas, Rect src, Rect dst, Bitmap bitmap)
{
dst = (dst == null ? new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()) : dst);
Paint paint = new Paint();
canvas.drawBitmap(bitmap, src, dst, paint);
}

/**

  • AnimationTransRunnable 做滑动动画所使用的线程
    */
    private class AnimationTransRunnable implements Runnable
    {
    private int srcX, dstX;
    private int duration;
/**
 * 滑动动画
 * @param srcX 滑动起始点
 * @param dstX 滑动终止点
 * @param duration 是否采用动画,1采用,0不采用
 */
public AnimationTransRunnable(float srcX, float dstX, final int duration)
{
  this.srcX = (int)srcX;
  this.dstX = (int)dstX;
  this.duration = duration;
}

@Override
public void run()
{
  final int patch = (dstX > srcX ? 5 : -5);
  if(duration == 0)
  {
    SlideSwitch.this.mSwitchStatus = SWITCH_SCROLING;
    SlideSwitch.this.postInvalidate();
  }
  else
  {
    int x = srcX + patch;
    while (Math.abs(x-dstX) > 5)
    {
      mDstX = x;
      SlideSwitch.this.mSwitchStatus = SWITCH_SCROLING;
      SlideSwitch.this.postInvalidate();
      x += patch;
      try
      {
        Thread.sleep(10);
      }
      catch (InterruptedException e)
      {
        e.printStackTrace();
      }
    }
    mDstX = dstX;
    SlideSwitch.this.mSwitchStatus = mDstX > 35 ? SWITCH_ON : SWITCH_OFF;
    SlideSwitch.this.postInvalidate();
  }
}

}

public static interface OnSwitchChangedListener
{
/**
* 状态改变 回调函数
* @param status SWITCH_ON表示打开 SWITCH_OFF表示关闭
*/
public abstract void onSwitchChanged(SlideSwitch obj, int status);
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为你提供一个基于Qt代码的左右滑动开关按钮的实现方法。 首先,我们需要在Qt的工程中添加一个自定义控件类。创建一个名为`SlideSwitch`的类,继承自`QWidget`,并在`.h`文件中添加以下代码: ``` class SlideSwitch : public QWidget { Q_OBJECT public: explicit SlideSwitch(QWidget *parent = nullptr); void setSwitchColor(const QColor &color); protected: void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; private: QColor m_switchColor; bool m_isOn; QPoint m_dragPos; }; ``` 然后,在`.cpp`文件中实现这些函数: ``` SlideSwitch::SlideSwitch(QWidget *parent) : QWidget(parent) { setFixedSize(60, 30); m_switchColor = QColor(0, 150, 136); m_isOn = false; } void SlideSwitch::setSwitchColor(const QColor &color) { m_switchColor = color; update(); } void SlideSwitch::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); QRectF bgRect(0, 0, width(), height()); QRectF switchRect(0, 0, height(), height()); switchRect.moveLeft(m_isOn ? width() - height() : 0); QBrush bgBrush(QColor(220, 220, 220)); painter.setBrush(bgBrush); painter.setPen(Qt::NoPen); painter.drawRoundedRect(bgRect, height() / 2, height() / 2); QBrush switchBrush(m_switchColor); painter.setBrush(switchBrush); painter.drawEllipse(switchRect); QWidget::paintEvent(event); } void SlideSwitch::mousePressEvent(QMouseEvent *event) { m_dragPos = event->pos(); } void SlideSwitch::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { int distance = event->pos().x() - m_dragPos.x(); if (m_isOn) { if (distance < 0) { m_isOn = false; update(); } } else { if (distance > 0) { m_isOn = true; update(); } } } } void SlideSwitch::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { int distance = event->pos().x() - m_dragPos.x(); if (m_isOn) { if (distance < 0) { m_isOn = false; update(); } } else { if (distance > 0) { m_isOn = true; update(); } } } } ``` 最后,在你的界面中使用这个自定义控件: ``` SlideSwitch *switchButton = new SlideSwitch(this); switchButton->setGeometry(10, 10, 60, 30); ``` 这样就完成了一个左右滑动开关按钮的实现啦!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值