Android中开关按钮IOS效果的实现
Android中开关按钮IOS效果的实现
自编自导自演 发表于2年前
Android中开关按钮IOS效果的实现
  • 发表于 2年前
  • 阅读 33
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 能够实现监听手指在按钮中的滑动。实现实时的开关闭合。
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.Scroller;

import com.fans.framework.utils.ViewUtils;
import com.fans.momhelpers.R;

/**
 * 选项
 * <p/>
 *声明 R.dimen.wXX  这种类型的是一个dp数字。这种是一种实时的适配方式
 *
 */
public class SwitchView extends ViewGroup implements View.OnTouchListener {

	private LinearLayout scrollView;// 滑块
	private int scrollWidth = 0;
	private Scroller scroller;
	private boolean checked = false;
	private View switchView;
	private int maskWidth;
	private Animation gone = AnimationUtils.loadAnimation(getContext(), R.anim.alpha_gone);
	private Animation show = AnimationUtils.loadAnimation(getContext(), R.anim.alpha_show);

	private OnCheckedChangedListener onCheckedChangedListener;// 监听选择变化
	private View bgView;

	public SwitchView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
		switchView.setBackgroundResource(R.drawable.switch_mask);
		maskWidth=(int) getResources().getDimension(R.dimen.w65);
		int checkedBg = R.drawable.switch_open;
		int normalBg = R.drawable.switch_close;
		setBackgroundResource(normalBg);
		Animation anim = new AlphaAnimation(0, 0);
		anim.setDuration(0);
		anim.setFillAfter(true);
		bgView.startAnimation(anim);
		bgView.setBackgroundResource(checkedBg);
	}

	/**
	 * 初始化
	 */
	private void init() {
		addView();
		scroller = new Scroller(getContext());
		scrollView.setOnTouchListener(this);
		show.setDuration(250);
		show.setFillAfter(true);
		gone.setDuration(250);
		gone.setFillAfter(true);
	}

	private int lastX = 0;
	private int marginLeft = 0;// 按压点距离左边的距离

	private long lastTime = 0;

	@Override
	public boolean onTouch(View view, MotionEvent motionEvent) {
		int x = (int) motionEvent.getX();
		switch (motionEvent.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (lastX == 0)
				lastX = x;
			if (marginLeft == 0)
				marginLeft = x + scrollView.getScrollX();
			lastTime = System.currentTimeMillis();
			break;
		case MotionEvent.ACTION_MOVE:
			int moveX = marginLeft - x;
			if (moveX > 0)
				scrollView.scrollTo(0, 0);
			else if (moveX < -scrollWidth)
				scrollView.scrollTo(-scrollWidth, 0);
			else
				scrollView.scrollTo(moveX, 0);
			lastX = x;
			break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_CANCEL:
			marginLeft = 0;
			if (System.currentTimeMillis() - lastTime <= 100) {
				if (checked)
					close();
				else
					open();
				onCheckedChanged();
				return true;
			}
			int center = scrollWidth / 2 - scrollView.getScrollX();// 滑块中间的X坐标
			if (center > scrollWidth) {// 超过中线
				open();
			} else {
				close();
			}
			onCheckedChanged();
			break;
		}
		return true;
	}

	/**
	 * 关闭动画
	 */
	private void close(int during) {
		int startX = scrollView.getScrollX();
		int dx = -startX;
		scroller.startScroll(startX, 0, dx, 0, during);
		if (checked && during > 0) {
			bgView.setVisibility(View.INVISIBLE);
			bgView.startAnimation(gone);
		} else {
			bgView.setVisibility(View.INVISIBLE);
		}
		invalidate();
		checked = false;
		// onCheckedChanged();
	}

	private void close() {
		close(250);
	}

	private void open() {
		open(250);
	}

	/**
	 * 开启动画
	 */
	private void open(int during) {
		int startX = scrollView.getScrollX();
		int dx = scrollWidth + startX;
		scroller.startScroll(startX, 0, -dx, 0, during);
		bgView.setVisibility(View.VISIBLE);
		if (!checked && during > 0) {
			bgView.startAnimation(show);
		} else {
			bgView.clearAnimation();
		}
		invalidate();
		checked = true;
		// onCheckedChanged();
	}

	public void setChecked(final boolean isCheck) {
		if (isChecked() == isCheck)
			return;
		if (scrollWidth > 0) {
			switchCheck(isCheck);
		} else {
			post(new Runnable() {

				@Override
				public void run() {
					switchCheck(isCheck);
				}

			});
		}
	}

	private void switchCheck(final boolean isCheck) {
		if (isCheck) {
			open(0);
		} else {
			close(0);
		}
	}

	/**
	 * 打开或者关闭时候调用
	 */
	private void onCheckedChanged() {
		if (onCheckedChangedListener != null)
			onCheckedChangedListener.onCheckedChanged(checked, this);
	}

	@Override
	public void computeScroll() {
		if (scroller.computeScrollOffset()) {
			scrollView.scrollTo(scroller.getCurrX(), scroller.getCurrY());
			postInvalidate();
		}
	}

	/**
	 * 是否打开
	 * 
	 * @return bool
	 */
	public boolean isChecked() {
		return checked;
	}

	/**
	 * 添加滑块
	 */
	private void addView() {
		LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		addView(bgView = new View(getContext()));
		scrollView = new LinearLayout(getContext());

		LinearLayout.LayoutParams maskParams = new LinearLayout.LayoutParams((int) getResources().getDimension(R.dimen.w65),
				(int) getResources().getDimension(R.dimen.w65));
		maskParams.gravity = Gravity.CENTER_VERTICAL;
		maskParams.topMargin = (int) getResources().getDimension(R.dimen.h3);
		scrollView.addView(switchView = new View(getContext()), maskParams);
		scrollView.addView(new View(getContext()), new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT, 1));
		addView(scrollView, params);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		View child = getChildAt(0);
		int height = child.getMeasuredHeight();
		int width = child.getMeasuredWidth();
		child.layout(0, 0, width, height);
		getChildAt(1).layout(0, 0, width, height);
		scrollWidth = width - maskWidth;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		// @dimen/w95
		// @dimen/w58
		// int width=get
		int width = ViewUtils.getDimenPx(R.dimen.w95);
		int height = ViewUtils.getDimenPx(R.dimen.w58);
		// int width = MeasureSpec.getSize(widthMeasureSpec);
		// int height = MeasureSpec.getSize(heightMeasureSpec);
		widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
		heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
		setMeasuredDimension(width, height);
		getChildAt(0).measure(widthMeasureSpec, heightMeasureSpec);
		getChildAt(1).measure(widthMeasureSpec, heightMeasureSpec);
	}

	/**
	 * 设置监听
	 * 
	 * @param listener
	 *            listener
	 */
	public void setOnCheckedChangedListener(OnCheckedChangedListener listener) {
		onCheckedChangedListener = listener;
	}

	public interface OnCheckedChangedListener {
		public void onCheckedChanged(boolean isChecked, SwitchView v);
	}
}

在res 中新建一个文件夹anim  然后添加两个动画

这个动画名字是 alpha_gone

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="250"
        android:fillAfter="true"/>
</set>

这个动画叫   alpha_show

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:duration="250" />

</set>

 现在已经完成了 你可以想实现CheackBox一样使用这个了

            <com.widget.SwitchView
                android:id="@+id/switch_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />


共有 人打赏支持
粉丝 4
博文 7
码字总数 9119
×
自编自导自演
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: