当前位置: 首页 > news >正文

自定义控件ToggleButton滑动开关

---恢复内容开始---

滑动开关--------
自定义控件步骤:
测量:onMeasure 设置自己显示在屏幕上的宽高
布局:onLayout 设置自己显示在屏幕上的位置(只有在自定义ViewGroup中才用到)
绘制:onDraw 控制显示在屏幕上的样子(自定义viewgroup时不需要这个)

View和ViewGroup的区别
1.他们都需要进行测量操作
2.ViewGroup主要是控制子view如何摆放,所以必须实现onLayout
View没有子view,所以不需要onLayout方法,但是必须实现onDraw

 

 

然后要想你设计这个控件能够有哪些功能?

1.设置滑动开关的背景图片,

2.设置滑动开关的滑块图片,

3.设置滑动开关的状态,

然后有了这些功能需求就可以进行代码的编写,

这次我们要自定义一个view,所以要继承view,实现它的构造方法,然后要实现设置图片的两个方法,和设置开关状态的方法,这里开关状态用了枚举类型。

因为绘制的时候只能绘制bitmap类型,所以要进行转化

    /**
     * 选择框的背景
     * 
     * @param icLauncher
     */
    public void setSwitchBackgroundResource(int icLauncher) {
        switchBg = BitmapFactory.decodeResource(getResources(), icLauncher);

    }

    /**
     * 滑动按钮背景
     * 
     * @param icLauncher
     */
    public void setSlideBackgroundResouce(int icLauncher) {
        slideBg = BitmapFactory.decodeResource(getResources(), icLauncher);
    }

    /**
     * 设置开关的初始状态
     * 
     * @param state
     */
    public void setSlideStare(ToggleState state) {
        togglestate = state;
    }

然后要重写测量方法,就是背景图片的宽高

/**
     * 设置当前控件显示在屏幕上的宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(switchBg.getWidth(), switchBg.getHeight());
    }

测量之后要进行绘制

首先绘制分为两种,

一种是滑动中绘制,

还有一种是不滑动根据设置的状态进行绘制

滑动中绘制:这个主要就是通过Touch事件来改变滑块距离左侧的值来进行绘制

@Override
    public boolean onTouchEvent(MotionEvent event) {
        //改变的值
     currentX
= (int) event.getX(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; // 松开的时候看当前X的值在哪里 case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_MOVE: break; } // 由它来调用ondraw方法 invalidate(); return true; }

绘制方法

    /*
             * 设置在正中间
             */
            int left = currentX - slideBg.getWidth() / 2;
            if (left < 0) {
                left = 0;
            } else if (left >= (switchBg.getWidth() - slideBg.getWidth())) {
                left = switchBg.getWidth() - slideBg.getWidth();
            }

另外一种就是不滑动根据状态绘制。首先要规定出状态,状态布尔值默认是false,然后当down变成true,当up时候重新变成false

// 绘制滑块
            // 判断滑块的状态
            // 打开
            if (togglestate == ToggleState.Open) {
                canvas.drawBitmap(slideBg,
                        switchBg.getWidth() - slideBg.getWidth(), 0, null);
                // 关闭
            } else {
                canvas.drawBitmap(slideBg, 0, 0, null);
            }

完整代码

package com.example.tbtn.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class ToggleButton extends View {
    // 设置的状态
    private ToggleState togglestate = ToggleState.Open;
    // 选择背景
    private Bitmap switchBg;
    // 滑动按钮背景
    private Bitmap slideBg;
    // 点击的X值
    private int currentX = 0;
    // 是否滑动
    private boolean isSliding = false;

    // 枚举类型
    public enum ToggleState {
        Open, Close
    }

    /**
     * 布局文件引用调用
     * 
     * @param context
     * @param attrs
     */
    public ToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    /**
     * 代码使用调用
     * 
     * @param context
     */
    public ToggleButton(Context context) {
        super(context);

    }

    /**
     * 选择框的背景
     * 
     * @param icLauncher
     */
    public void setSwitchBackgroundResource(int icLauncher) {
        switchBg = BitmapFactory.decodeResource(getResources(), icLauncher);

    }

    /**
     * 滑动按钮背景
     * 
     * @param icLauncher
     */
    public void setSlideBackgroundResouce(int icLauncher) {
        slideBg = BitmapFactory.decodeResource(getResources(), icLauncher);
    }

    /**
     * 设置开关的初始状态
     * 
     * @param state
     */
    public void setSlideStare(ToggleState state) {
        togglestate = state;
    }

    /**
     * 设置当前控件显示在屏幕上的宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(switchBg.getWidth(), switchBg.getHeight());
    }

    /**
     * 绘制
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        // left 距图片左侧 top 距图片上部
        canvas.drawBitmap(switchBg, 0, 0, null);

        if (isSliding) {
            /*
             * 设置按在正中间
             */
            int left = currentX - slideBg.getWidth() / 2;
            if (left < 0) {
                left = 0;
            } else if (left >= (switchBg.getWidth() - slideBg.getWidth())) {
                left = switchBg.getWidth() - slideBg.getWidth();
            }
            canvas.drawBitmap(slideBg, left, 0, null);
        } else {
            // 绘制滑块
            // 判断滑块的状态
            // 打开
            if (togglestate == ToggleState.Open) {
                canvas.drawBitmap(slideBg,
                        switchBg.getWidth() - slideBg.getWidth(), 0, null);
                // 关闭
            } else {
                canvas.drawBitmap(slideBg, 0, 0, null);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        currentX = (int) event.getX();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            isSliding = true;
            break;
        // 松开的时候看当前X的值在哪里
        case MotionEvent.ACTION_UP:
            isSliding = false;
            // 图片中心点
            int centerX = switchBg.getWidth() / 2;
            // 打开
            if (currentX > centerX) {
                // 判断当前状态是否真的改变(就是滑动一半回去了)
                if (togglestate != ToggleState.Open) {
                    togglestate = ToggleState.Open;
                    // 设置回调借口
                    if (lisern != null) {
                        lisern.onToggleChange(togglestate);
                    }
                }
                // 关闭
            } else {
                if (togglestate != ToggleState.Close) {
                    togglestate = ToggleState.Close;
                    // 设置回调借口
                    if (lisern != null) {
                        lisern.onToggleChange(togglestate);
                    }
                }
            }

            break;
        case MotionEvent.ACTION_MOVE:

            break;
        }
        // 由它来调用ondraw方法
        invalidate();
        return true;
    }

    private OnToggleChangeLisern lisern;

    public void setOnToggleChangeLisern(OnToggleChangeLisern lisern) {
        this.lisern = lisern;
    }

    // 回调接口
    public interface OnToggleChangeLisern {
        void onToggleChange(ToggleState state);
    }

}

 Activity中使用

package com.example.tbtn;

import com.example.tbtn.view.ToggleButton;
import com.example.tbtn.view.ToggleButton.OnToggleChangeLisern;
import com.example.tbtn.view.ToggleButton.ToggleState;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;


public class MainActivity extends Activity {
    private ToggleButton tBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tBtn = (ToggleButton) findViewById(R.id.tbtn);
        tBtn.setSwitchBackgroundResource(R.drawable.togglebtn);
        tBtn.setSlideBackgroundResouce(R.drawable.ic_launcher);
        tBtn.setSlideStare(ToggleState.Open);
        tBtn.setOnToggleChangeLisern(new OnToggleChangeLisern() {
            
            @Override
            public void onToggleChange(ToggleState state) {
                if(state==ToggleState.Open){
                    Toast.makeText(MainActivity.this,"打开", 0).show();
                }else{
                    Toast.makeText(MainActivity.this,"关闭", 0).show();
                }
                
            }
        });
    }

}

 

转载于:https://www.cnblogs.com/84126858jmz/p/5175625.html

相关文章:

  • 关于初高中虚拟仿真实验室解决方案
  • udp开发-dtd验证,dom解析
  • 不创建第三方变量对整型数组逆置
  • 封装一个地图中间件,愉快的切换百度地图和谷歌地图...
  • ListView的属性详解和探究
  • Javascript模块化编程(三):require.js的用法
  • 《Node.js入门》CentOS 6.5下Node.js Web开发环境搭建笔记
  • Xms Xmx PermSize MaxPermSize 区别
  • ssh 远程登陆 refuse
  • 使用Flexible实现手淘H5页面的终端适配的注意事项
  • Installing and Using Standby Statspack in 11g
  • 美国:《网络安全国家行动计划》(2016年2月)
  • CentOS 目录结构
  • php7安装笔记,个人零时笔记
  • ioS开发知识(二十八)
  • [译]前端离线指南(上)
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • angular组件开发
  • Mysql数据库的条件查询语句
  • Python_OOP
  • sublime配置文件
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 从伪并行的 Python 多线程说起
  • 复杂数据处理
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 七牛云假注销小指南
  • 前嗅ForeSpider教程:创建模板
  • 浅谈Golang中select的用法
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 网络应用优化——时延与带宽
  • NLPIR智能语义技术让大数据挖掘更简单
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #每天一道面试题# 什么是MySQL的回表查询
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (2.2w字)前端单元测试之Jest详解篇
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (二十四)Flask之flask-session组件
  • (剑指Offer)面试题34:丑数
  • (算法)Game
  • (一)u-boot-nand.bin的下载
  • (转)iOS字体
  • (转)shell调试方法
  • (转载)Linux网络编程入门
  • *1 计算机基础和操作系统基础及几大协议
  • .axf 转化 .bin文件 的方法
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET MVC 验证码
  • .NET 使用配置文件
  • .Net环境下的缓存技术介绍
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • /dev/sda2 is mounted; will not make a filesystem here!