android之自定义switch

本文介绍了如何在Android中自定义Switch控件MySwitch,它不仅支持所有SDK,还新增了两个特性:使用Track背景图片展示开关状态和调整Switch高度。关键代码包括对MySwitch的构造函数和触摸事件的处理,以及布局和绘制方法的重写,以实现自定义功能。
摘要由CSDN通过智能技术生成


     最近项目中需要到自定义的switch控件,但是google原生的switch空间不符合客户的需求,客户要求仿OPPO的switch样式,因此自己查资料做了一个,基本功能与原生无差别,样式可根据自身的实际需求做修改

      修改Switch的主要思想是:1. Switch中含有高版本SDK代码,需要去掉或者改写这样的代码  2. Switch对应declare-styleable属性声明应该在Android SDK安装目录中找到对应的源码声明片段,基本上copy过来就行了。所在路径:\Android\android-sdk\platforms\android-17\data\res

修改后的MySwitch控件接口基本与原Switch控件一致,并且除了可支持所有SDK外,增加了2项小功能:

1. 支持用Track背景图片的方式代替Texton Textoff等文字方式表现开关状态

2.支持调整控制Switch的高度

下面贴出Switch修改的关键代码:

1.MySwitch.java

package com.test.wison;
 
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.widget.CompoundButton;
import android.widget.Switch;
 
/**
 * A Switch is a two-state toggle switch widget that can select between two
 * options. The user may drag the "thumb" back and forth to choose the selected option,
 * or simply tap to toggle as if it were a checkbox. The {@link #setText(CharSequence) text}
 * property controls the text displayed in the label for the switch, whereas the
 * {@link #setTextOff(CharSequence) off} and {@link #setTextOn(CharSequence) on} text
 * controls the text on the thumb. Similarly, the
 * {@link #setTextAppearance(android.content.Context, int) textAppearance} and the related
 * setTypeface() methods control the typeface and style of label text, whereas the
 * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and
 * the related seSwitchTypeface() methods control that of the thumb.
 *  
 * <p>  
 * modified from android SDK 14(4.0) android.widget.Switch.
 * <br/>
 * <strong>new feature: </strong>
 * <ol>
 * <li>support SDK 1 or higher. </li>
 * <li>you can use track drawable instead of text to display the changes of off-on state!</li>
 * <li>you can control the Switch minimum height. </li>
 * </ol>
 * </p>
 *    
 *    @see {@link Switch}
 *    @author Wison
 */
public class MySwitch extends CompoundButton {
    private static final int TOUCH_MODE_IDLE = 0;
    private static final int TOUCH_MODE_DOWN = 1;
    private static final int TOUCH_MODE_DRAGGING = 2;
 
    // Support track drawable instead of text
    private Drawable mTrackOnDrawable;
    private Drawable mTrackOffDrawable;
     
    // Enum for the "typeface" XML parameter.
    private static final int SANS = 1;
    private static final int SERIF = 2;
    private static final int MONOSPACE = 3;
 
    private Drawable mThumbDrawable;
    private Drawable mTrackDrawable;
    private int mThumbTextPadding;
    private int mSwitchMinWidth;
     
    // Support minimum height
    private int mSwitchMinHeight;
     
    private int mSwitchPadding;
    private CharSequence mTextOn;
    private CharSequence mTextOff;
 
    private int mTouchMode;
    private int mTouchSlop;
    private float mTouchX;
    private float mTouchY;
    @SuppressLint("Recycle")
    private VelocityTracker mVelocityTracker = VelocityTracker.obtain();
    private int mMinFlingVelocity;
 
    private float mThumbPosition;
    private int mSwitchWidth;
    private int mSwitchHeight;
    private int mThumbWidth; // Does not include padding
 
    private int mSwitchLeft;
    private int mSwitchTop;
    private int mSwitchRight;
    private int mSwitchBottom;
 
    private TextPaint mTextPaint;
    private ColorStateList mTextColors;
    private Layout mOnLayout;
    private Layout mOffLayout;
 
//    @SuppressWarnings("hiding")
    private final Rect mTempRect = new Rect();
 
    private static final int[] CHECKED_STATE_SET = {
        android.R.attr.state_checked
    };
 
    /**
     * Construct a new Switch with default styling.
     *
     * @param context The Context that will determine this widget's theming.
     */
    public MySwitch(Context context) {
        this(context, null);
    }
 
    /**
     * Construct a new Switch with default styling, overriding specific style
     * attributes as requested.
     *
     * @param context The Context that will determine this widget's theming.
     * @param attrs Specification of attributes that should deviate from default styling.
     */
    public MySwitch(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.switchStyle);
    }
 
    /**
     * Construct a new Switch with a default style determined by the given theme attribute,
     * overriding specific style attributes as requested.
     *
     * @param context The Context that will determine this widget's theming.
     * @param attrs Specification of attributes that should deviate from the default styling.
     * @param defStyle An attribute ID within the active theme containing a reference to the
     *                 default style for this widget. e.g. android.R.attr.switchStyle.
     */
    public MySwitch(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
 
        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        Resources res = getResources();
        mTextPaint.density = res.getDisplayMetrics().density;
        //float scaledDensity = res.getDisplayMetrics().scaledDensity;
        //mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
 
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Switch, defStyle, 0);
 
        // off-on 模式�?图片模式或文字模式,图片模式是用Track背景图片表示off-on的状态,文字模式是用文字来表示off-on状�?�?
        mTrackOnDrawable = a.getDrawable(R.styleable.Switch_trackOn);
        mTrackOffDrawable = a.getDrawable(R.styleable.Switch_trackOff);
        if (checkTrackOffOnDrawable()) {
            // 如果设定图片模式,则默认显示off状�?
            mTrackDrawable = mTrackOffDrawable;
        } else {
            mTrackDrawable = a.getDrawable(R.styleable.Switch_track);
        }
         
        mThumbDrawable = a.getDrawable(R.styleable.Switch_thumb);
        mTextOn = a.getText(R.styleable.Switch_textOn);
        mTextOff = a.getText(R.styleable.Switch_textOff);
        mThumbTextPadding = a.getDimensionPixelSize(R.styleable.Switch_thumbTextPadding, 0);
        mSwitchMinWidth = a.getDimensionPixelSize(R.styleable.Switch_switchMinWidth, 0);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值