zoukankan      html  css  js  c++  java
  • 自定义控件如同系统控件:自定义控件,画空间图片,定义空间属性,构造监听器。

      android的基本控件很难满足用户的需求,因此有时候用户需要根据美工设置的一些图片来自定义一些控件,不多说,现在介绍一下,自定义一个开关控件的流程,让大家更了解控件的工作原理:

    1、首先构建一个控件的类,继承view,这时候需要覆写view的构造方法。同时需要把美工美化好的图片拖到drawable目录下。在控件初始化的时候需要加载进美工的图片即:背景bg和开关滑动钮swicher。注意加载图片时候R.drawable时候有2个注意别选错了,否则找不到图片的id。

    2、android的控件都是通过view下的Ondraw()方法画上去的,因此要覆写view的Oncreate方法将bg和swicher画上去。画画需要画纸和笔,因此在初始化的时候构建一支笔,画板系统提供,即参数里的canvas.里面的参数分别是图、上,左的坐标和笔。因此我们要设定的就是画的位置就是上左的坐标即可。

    3、这时候我们可以在xml文件里可以添加这个控件看看效果了,注意添加空间时候一定加上包名和类名(不要带上class如:<com.example.togglebutton.ui.MytoggleButton即可,同时在最上面加上控件的命名空间:复制android的,并将android改成这个程序的包名即可。注意的是,默认下控件大小是屏幕的长宽,因此需要调用onMeasure()方法测量宽高和setMeasuredDimension()重新设定宽高。

    4、为了让空间可以拖动,就必须覆写view的onTouchEvent()方法,注意所有的触摸事件的方法都是由这个方法来处理的,然后监听:落下、滑动、离开这3个动作(想更复杂的也可以监听别的事件),通过打印发现只能监听到“落下”的事件,原来这个方法默认是系统处理的,若想用户自己处理就必须将return surper.onTouchEvent()修改成return true;(ps:当你的控件继承其他的具体控件时候,若继承的空间有自己的监听器接口时候,这里就不能改为true,并且已经可监听到,因为继承的控件已经覆写了View的OntouchEvent事件了,若该为true时候继承的操作就失效了)。

    5、设定事件处理,我们根据ondraw方法画图,里设定坐标时候将左设定为类的成员变量,上为0,因此当我们改变left的值,然后调用invalidate()刷新操作调用ondraw()方法来重新画图即可。

    6、设定控件的属性,这里就添加一个状态state当作事例,首先在values里创建一个xml文件,然后在xml文件里声明、定义属性atrrs。如果大家不记得就可以参考安装的sdk目录下android自带属性的定义:sdkplatformsandroid-19data esvaluesattrs.xml。并且在构造方法:public MytoggleButton(Context context, AttributeSet attrs)里解析属性,好在配置文件中使用属性,并且里面设置默认属性值。

    7、在类里给出设定state和得到state的函数,并将state作为函数的成员变量。

    8、给空间设定监听事件,这里就定义一个监听state发生改变的接口,在接口里声明state发生变化的方法。然后将接口作为类的成员变量,为类设定一个设置监听器的函数,将接口作为参数,因此设置监听器必须实现这个接口,然后把实现额接口复制给类成员变量。

    9在ontouchEvent()的up里先判断状态是否改变,若改变就利用实例化了接口的类来调用接口的onchange方法就完成了状态放生改变的监听事件。

    下面给出完整的demo:

    main.xml文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:myview="http://schemas.android.com/apk/res/com.example.togglebutton.ui"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.togglebutton.MainActivity$PlaceholderFragment"
        android:background="#ffff00"
         >
    
        <com.example.togglebutton.ui.MytoggleButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            myview:state="true"
            android:id="@+id/togglebutton"
           />
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/text"
          	android:layout_centerVertical="true"
          	android:layout_centerHorizontal="true"
            
            />
    
    </RelativeLayout>
    

      values 下的属性定义文件atrrs.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <declare-styleable name="myview">
       <attr name="state" format="boolean" />
         </declare-styleable>
    </resources>
    

      开关控件类的定义

    package com.example.togglebutton.ui;
    
    import com.example.togglebutton.R;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.drawable.BitmapDrawable;
    import android.text.Editable.Factory;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    public class MytoggleButton extends View {
    	private Context context; 
    	private Bitmap bg;
    	private Bitmap sw;
    	private Paint paint;
    	private  int maxleft;
    	private int left;
    	private  boolean state;
    	
    	private OnMytoggleButtonStateChangeLitener onMytoggleButtonStateChangeLitener;
    	
    	public void setOnMytoggleButtonStateChangeLitener(OnMytoggleButtonStateChangeLitener l)
    	{
    		onMytoggleButtonStateChangeLitener=l;
    	}
    	
    	
    	public MytoggleButton(Context context) {
    		super(context);
    		this.context=context;
    		init();
    	}
    
    	//这里是解析属性的AttributeSet attrs,可以在配置文件中使用这些属性
    	public MytoggleButton(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		this.context=context;	
    		init();
    		//解析属性
    		String namespace="http://schemas.android.com/apk/res/com.example.togglebutton";
    		state=attrs.getAttributeBooleanValue(namespace, "state", true);//默认为关
    		if(state==false)
    			left=0;
    		else
    			left=maxleft;
    		
    	}
    
    	public MytoggleButton(Context context, AttributeSet attrs, int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    		this.context=context;	
    		init();
    		}
    	//初始化
    	public void init()
    	{
    		 paint=new Paint();
    		 sw=BitmapFactory.decodeResource(getResources(), R.drawable.slide_button_background);
    		 bg=BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
    		 maxleft=bg.getWidth()-sw.getWidth();
    	}
    
    	public void setState(boolean state)
    	{
    		if(state=true)
    			{
    			left=maxleft;
    			state=true;
    			}
    		else 
    			{
    			state=false;
    			left=0;
    			}
    		invalidate();
    	}
    	public boolean getState()
    	{
    		return state;
    	}
    	
    	@Override//这是空间开始创建时会运行一次
    	protected void onDraw(Canvas canvas) {
    		
    		canvas.drawBitmap(bg, 0, 0, paint);
    		canvas.drawBitmap(sw, left, 0,paint);
    		super.onDraw(canvas);
    		
    	}
    
    	
    	
    	
    	@Override//限制空间高宽
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    		setMeasuredDimension(bg.getWidth(), bg.getHeight());
    	}
    
    	int startX=0;
    	int currentX=0;
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		
    	
    		
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			startX=(int) event.getX();
    			System.out.println("down"+state);
    			break;
    		case MotionEvent.ACTION_MOVE:
    			currentX=(int) event.getX();
    			int d=currentX-startX;
    			left=d+left;
    			if(left>=maxleft)
    				left=maxleft;
    			else if(left<=0)
    				left=0;
    			System.out.println("move"+state);
    			break;
    		case MotionEvent.ACTION_UP:
    			boolean stateOlder=state;
    			System.out.println("up"+state);
    			if(left>maxleft/2)
    			{
    				left=maxleft;
    				state=true;
    				}
    			else
    			{
    				left=0;
    				state=false;
    				}
    			
    			if(state!=stateOlder&&onMytoggleButtonStateChangeLitener!=null)
    				onMytoggleButtonStateChangeLitener.stateChange(getState());
    			
    			break;
    
    		default:
    			break;
    		}
    	
    		invalidate();//刷新画图,调用空间的ondrow()方法
    		return true;//super.onTouchEvent(event);
    	}
    	
    	
    }
    

      activity文件:

    public class MainActivity extends Activity {
    
    	private MytoggleButton togglebutton;
    	private TextView tx;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        	
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
           
            togglebutton=(MytoggleButton) findViewById(R.id.togglebutton);
            tx=(TextView) findViewById(R.id.text);
            tx.setText("State:"+(togglebutton.getState()?"开":"关"));
            togglebutton.setOnMytoggleButtonStateChangeLitener(new OnMytoggleButtonStateChangeLitener(){
    
    			@Override
    			public void stateChange(boolean state) {
    				 tx.setText("State:"+(togglebutton.getState()?"开":"关"));
    			}
            }
            		);
            
        }
    }
    

      

  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/4768760.html
Copyright © 2011-2022 走看看