zoukankan      html  css  js  c++  java
  • android 仿ios开关控件

    ios一些控件还是挺美丽的,可是对android程序猿来说可能比較苦逼,由于ios一些看起来简单的效果对android来说可能就没那么简单了,可是没办法非常多产品都是拿ios的一些控件叫android开发者来照着做,今天就来做一个设置中常见的开关效果,

    思路:

    1:准备二张图片 一个是包括开和关二种状态的图片,一个是上面滑动的button图片

    2:这些图片肯定是不能通过原生态的控件显示上去的,要通过canvas画上去

    3:要解决点击和滑动的事件冲突,由于点击包括 按下 离开,而滑动包括按下  移动 离开,


    以下看代码逻辑首先是布局文件,非常easy

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <com.example.toggle.ui.MyToggleView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
          android:layout_centerInParent="true"
           />
    </RelativeLayout>
    
    MyToggleView.java 自己定义的控件

    package com.example.toggle.ui;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    
    import com.example.toggle.R;
    /**
     * 一个view从创建到显示要经历的过程
     * 1:构造函数 实例初始化
     * 2:測量 onMeasure
     * 3:假设当前view是ViewGroup 还要义务測量它孩子(子view)
     * 4:指定控件的大小和位置 (onLayout)
     * 假设当前view是ViewGroup 还要义务指定它孩子的大小和位置(子view)
     * 5:绘制(就是画出来再屏幕上可见)onDraw(Canvas canvas)
     * @author Administrator
     * 
     * 点击事件包括点击 和 离开  而这个离开刚好和移动中的up事件一样
     *
     */
    public class MyToggleView extends View implements View.OnClickListener {
    	private static final String TAG = "MyToggleView";
    	Paint paint ;
    	private Bitmap bg_bitmap;
    	private Bitmap sliding_bitmap;
    	private float slidingLeft = 0;
    	private int slideLeftMax;
    	/**
    	 * 自己定义样式用它
    	 * @param context
    	 * @param attrs
    	 * @param defStyleAttr
    	 */
    	public MyToggleView(Context context, AttributeSet attrs, int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    	}
    	/**
    	 * 在布局时候用它
    	 * @param context
    	 * @param attrs
    	 */
    	public MyToggleView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		initView();
    	}
    	private void initView() {
    		paint = new Paint();
    		bg_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
    		sliding_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
    		slideLeftMax = bg_bitmap.getWidth() - sliding_bitmap.getWidth();		
    		setOnClickListener(this);
    	}
    	/**
    	 * 在代码new的时候用它
    	 * @param context
    	 */
    	public MyToggleView(Context context) {
    		super(context);
    	}
    	/**
    	 * 測量
    	 */
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		/**
    		 * 这是父类去測量子view的大小 而我们能够不要父类去測量
    		 */
    //		super.onMeasure(bg_bitmap.getWidth(), bg_bitmap.getHeight());
    		/**
    		 * 人为指定控件測量大小 (就是说没有測量)
    		 */
    		setMeasuredDimension(bg_bitmap.getWidth(), bg_bitmap.getHeight());
    	}
    	@Override
    	protected void onDraw(Canvas canvas) {
    		canvas.drawBitmap(bg_bitmap, 0, 0, paint);
    		canvas.drawBitmap(sliding_bitmap, slidingLeft , 0, paint);
    	}
    	private boolean isOpened = false;
    	/**
    	 * isClickenble为true表示点击事件生效 但触摸事件无效
    	 * isClickenble 为false表示点击事件失效 触摸事件有效
    	 */
    	private boolean isClickenble = false;
    	@Override
    	public void onClick(View v) {
    		if(isClickenble){
    			isOpened = !isOpened;
    			if(isOpened){
    				slidingLeft = bg_bitmap.getWidth()-sliding_bitmap.getWidth();
    			}else{
    				slidingLeft = 0;
    			}
    			invalidate();
    		}
    	}
    	private float startX = 0;//手指刚触动时候的x轴坐标
    	private float lastX = 0;//手指刚触动时候的x轴坐标
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		 super.onTouchEvent(event);//运行父类的方法
    		switch (event.getAction()) {//推断滑动的动作 是刚按下 还是拖动 还是手指 抬起
    		case MotionEvent.ACTION_DOWN :
    			lastX = startX = event.getX();//这是距离 这个控件的x轴坐标值
    			isClickenble = true;
    			break;
    		case MotionEvent.ACTION_MOVE :
    			float endX = event.getX();
    			int distanceX = (int) Math.abs(endX - lastX);
    			if(distanceX > 5){
    				isClickenble = false;
    			}
    			refreshView(endX);
    			startX = event.getX();//又一次计算初始值
    			break;
    		case MotionEvent.ACTION_UP :
    			if(slidingLeft>slideLeftMax/2){ //开
    				isOpened = true;
    				slidingLeft = slideLeftMax;
    			}else{//关
    				isOpened = false;
    				slidingLeft = 0;
    			}
    			invalidate();
    			break;
    		}
    		return true;//表示自己处理 不须要调用父类的方法
    	}
    	private void refreshView(float endX) {
    		float distance  = (endX - startX) ; 
    		slidingLeft+=distance;
    		if(slidingLeft<0){
    			slidingLeft = 0;
    		}
    		if(slidingLeft>slideLeftMax){
    			slidingLeft = slideLeftMax;
    		}
    		invalidate();
    	}
    }
    

    效果图:



  • 相关阅读:
    pcs7 opc 连接问题
    nuget 多个程序引用同一个库时,当个这个库更新时,引用的程序都要跟新,否则会在运行时出错
    nuget update FileConflictAction
    a
    C#版本
    .NET Framework版本与CLR版本之间的关系
    c# 将一种数组类型转成另一种数组类型
    tfs 清除缓存,在需要时
    java枚举和仿枚举
    java反射的用法
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7234766.html
Copyright © 2011-2022 走看看