自定义View(二)

自定义View(二)

  1. 添加了响应触摸事件;
  2. 设置接口回调,创建一个状态更新监听;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View {

    private Bitmap backgroundBitmap;
    private Bitmap carBitmap;
    private Paint paint;
    private boolean place = false;
    private float currentX;
    private OnSwitchStateListener onSwitchStateListener;

    public MyView(Context context) {
        super(context);
    }
    public MyView(Context context, AttributeSet attr){
        super(context,attr);
        paint = new Paint();
        //获取配置的资源属性
        String namespace = "http://schemas.android.com/apk/res/com.example.myapplication1";
        int backgroundResource = attr.getAttributeResourceValue(namespace,"switch_backgroundRoadTarget",-1);
        setTarget(backgroundResource);
        int carResource = attr.getAttributeResourceValue(namespace,"slide_carImage",-1);
        setImage(carResource);
        attr.getAttributeBooleanValue(namespace,"switch_state",false);
    }
    public MyView(Context context, AttributeSet attr,int defStyle){
        super(context,attr,defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);不用此方法,重写父类的方法
        setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());
    }

    @Override
    protected void onDraw(Canvas canvas) {//Canvas画板,先绘制在下面,绘制内容都会显示到界面上
        super.onDraw(canvas);
        //1.绘制背景
        canvas.drawBitmap(backgroundBitmap,0,50,paint);
        //2.绘制滑块
        if(isTouch){
            //根据用户触摸位置画滑块
           float left = currentX - carBitmap.getWidth()/2.0f;//写2.0f为了精度
            int maxLeft = backgroundBitmap.getWidth() - carBitmap.getWidth();
            //限定滑块范围
            if(left < 0){
                left = 0;
            }
            if(left > maxLeft){
                left = maxLeft;
            }
            canvas.drawBitmap(carBitmap,left,0,paint);

        }else{
            if(place){//右侧
                int roadlong = backgroundBitmap.getWidth() - carBitmap.getWidth();
                canvas.drawBitmap(carBitmap,roadlong,0,paint);
            }else{//左侧
                canvas.drawBitmap(carBitmap,0,0,paint);
            }
        }


    }
    boolean isTouch = false;
    //重写触摸事件,响应用户的触摸
    @Override
    public boolean onTouchEvent(MotionEvent event) {
       // return super.onTouchEvent(event);在工具类里重写方法
        switch (event.getAction()){
            case  MotionEvent.ACTION_DOWN:
                isTouch = true;
                currentX = event.getX();

                break;
            case  MotionEvent.ACTION_MOVE:
                currentX = event.getX();
                break;
            case  MotionEvent.ACTION_UP:
                isTouch = false;
                currentX = event.getX();
                float center = backgroundBitmap.getWidth()/2.0f;
                boolean newPlace = currentX > center;//true or false
                //若状态变化,通知界面,状态更新
                if(place != newPlace && onSwitchStateListener != null){
                    onSwitchStateListener.onStateUpdate(newPlace);
                }
                place = newPlace;
                break;
            default:
                break;
        }
        //重绘界面 onDraw()方法是手动调用
        invalidate();//会引发onDraw()方法被调用,变量会重新被调用

        return  true;
    }

    public void setTarget(int target) {
        backgroundBitmap = BitmapFactory.decodeResource(getResources(),target);
    }

    public void setImage(int slideImage) {
        carBitmap = BitmapFactory.decodeResource(getResources(),slideImage);
    }

    public void setState(boolean place) {
    this.place = place;
    }
    public  interface OnSwitchStateListener{
        //状态改变,把状态信息传出去
        void onStateUpdate(boolean state);
    }
    public  void setOnSwitchStateListener(OnSwitchStateListener onSwitchStateListener){
        this.onSwitchStateListener = onSwitchStateListener;
    }
}

理解:
在MyView里声明接口对象

 public  interface OnSwitchStateListener{
        //状态改变,把状态信息传出去
        void onStateUpdate(boolean state);
    }
   

添加设置接口对象的方法,外部进行调用

      public  void setOnSwitchStateListener(OnSwitchStateListener onSwitchStateListener){//界面调用的方法
        this.onSwitchStateListener = onSwitchStateListener;
    }

状态发生变化,在MyView中合适位置执行接口方法

 //若状态变化,通知界面,状态更新
                if(place != newPlace && onSwitchStateListener != null){
                    onSwitchStateListener.onStateUpdate(newPlace);
                }

MainActivity里设置状态更新监听

    myView.setOnSwitchStateListener(new MyView.OnSwitchStateListener(){
            @Override
            //匿名类中实现方法onStateUpdate(boolean state)
            public void onStateUpdate(boolean state) {
                Toast.makeText(getApplicationContext(),"state"+state,Toast.LENGTH_SHORT).show();
            }
        });

自定义属性

创建attrs.xml
reference:参考某一资源ID。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView">
        <attr name="switch_backgroundRoadTarget" format="reference"/>
        <attr name="slide_carImage" format="reference"/>
        <attr name="switch_state" format="boolean"/>
    </declare-styleable>
</resources>

xml文件里设置属性
xmlns:viewstyle=“http://schemas.android.com/apk/res/com.example.myapplication1”
viewstyle:瞎起的名字,定义属性时需要用
http://schemas.android.com/apk/res/com.example.myapplication1:com.example.myapplication1表示MyView所在的包名
<com.example.myapplication1.MyView
android:id="@+id/smileview"
android:background="#FF0000"
viewstyle:switch_backgroundRoadTarget="@drawable/road1"
viewstyle:slide_carImage="@drawable/car1"
viewstyle:switch_state="false"

android:layout_gravity=“center_vertical”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>

在MyView里

  public MyView(Context context, AttributeSet attr){
        super(context,attr);
        paint = new Paint();
        //获取配置的资源属性
        String namespace = "http://schemas.android.com/apk/res/com.example.myapplication1";
        int backgroundResource = attr.getAttributeResourceValue(namespace,"switch_backgroundRoadTarget",-1);
        setTarget(backgroundResource);
        int carResource = attr.getAttributeResourceValue(namespace,"slide_carImage",-1);
        setImage(carResource);
        attr.getAttributeBooleanValue(namespace,"switch_state",false);
    }

自定义View的使用参考b站上大佬 雇佣兵并的视频。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值