功能简介

自绘制的仿ios的上下滑动改变亮度大小组件,虚拟机里不起作用,没有改变亮度,但是真实机器上有效果。

相关文章讲解:


在这里插入图片描述


主要实现步骤

1.定义一个音量比例mCurrentDrawBrightnessRate,该比例作为当前亮度展示在view里的高度。view总高度为1,音量比例处于0 ~ 1 之间

2.通过onTouchEvent方法获取手指在view内部上下移动的距离并重新计算音量比例。mCurrentDrawBrightnessRate= (当前音量*view总高度 + 上下移动距离)/ view总高度
3.用音量比例去绘制圆柱体前景颜色高度,高度为 音量比例 * view总高度。难点在于如何绘制前景颜色贴合背景,可以看见白色区域是被灰色背景切割的,即使是圆弧的区域也是。这里用到了setXfermode方法,
4.画亮度的太阳图标,太阳图标圆心和光芒皆会随着亮度的提高而扩大,反之则相反。
5.详细步骤看代码,(完整代码可以看github项目)另外该view长宽已经写死,没有进行多余的适配


xml相关属性设置

属性名介绍
iosColumnAudioView_setAudioStreamType设置想要改变的声音模式
iosColumnAudioView_setColorBackground圆柱体底部背景颜色
iosColumnBrightnessView_setColorBright圆柱体内部颜色,代表亮度大小
iosColumnAudioView_setRadiusXY圆柱体的圆弧
iosColumnAudioView_setTextSize亮度字体大小
iosColumnAudioView_setTextColor亮度字体颜色
iosColumnAudioView_setTextHeight亮度字体高度
iosColumnBrightnessView_setIsDrawTextBright是否绘制亮度字体
iosColumnBrightnessView_setIsDrawDrawableBright是否绘制亮度图标
iosColumnBrightnessView_setBrightnessColor亮度图标颜色

java代码

public class IosColumnBrightnessView extends View {
    private Context mContext;
    //日志TAG
    private static final String TAG = IosColumnBrightnessView.class.getName();
    //系统亮度监听
    private BrightnessObserver mBrightnessObserver = null;
    //当前圆心最大半径
    private float mCircleMaxRadius = 0;
    //当前圆心最小半径
    private float mCircleMinRadius = 0;
    //当前圆心边长
    private float mCircleMaxWidth = 0;
    //当前UI高度与view高度的比例
    private double mCurrentDrawBrightnessRate = 0;
    //系统最大亮度index-默认255
    private final int mMaxBrightness = 255;
    //记录按压时手指相对于组件view的高度
    private float mDownY;
    //手指移动的距离,视为亮度调整
    private float mMoveDistance;
    //系统audio管理
    private AudioManager mAudioManager;
    //当前亮度文字数字
    private String mTextLoud ="";
    //画笔
    private Paint mPaint;
    //位置
    private RectF mRectF;
    //当前Canvas LayerId
    private int layerId = 0;
    //亮度图标margin
    private int mRectBrightnessDrawableMargin =10;
    //亮度图标粗细
    private final static int mRectBrightnessDrawableWidth =4;

    /**
     * 设置圆弧度数-xml-iosColumnAudioView_setRadiusXY
     */
    private float mRXY=40;
    /**
     * 设置当前亮度颜色-xml-iosColumnAudioView_setColorLoud
     */
    private int mColorLoud = Color.parseColor("#ECECEC");
    /**
     * 设置组件背景颜色-xml-iosColumnAudioView_setColorBackground
     */
    private int mColorBackground = Color.parseColor("#898989");

    /**
     * 设置是否画亮度文字-iosColumnAudioView_setIsDrawTextVolume
     * @param context
     */
    private boolean mIsDrawTextVolume = true;
    /**
     * 设置文字大小-xml-iosColumnAudioView_setTextSize
     */
    private float mTextSize = 15;
    /**
     * 设置文字颜色-xml-iosColumnAudioView_setTextColor
     */
    private int mTextColor = Color.BLACK;
    /**
     * 设置文字高度-xml-iosColumnAudioView_setTextHeight
     * @param context
     */
    private int mTextHeight = -1;
    /**
     * 设置是否画亮度图标-iosColumnAudioView_setIsDrawDrawableVolume
     * @param context
     */
    private boolean mIsDrawDrawableVolume = true;
    /**
     * 设置亮度圆弧颜色-xml-iosColumnAudioView_setColorVolume
     */
    private int mColorVolume = Color.DKGRAY;
    //固定组件高度长度,这里不做适配,可自行修改
    private int mViewHeight = 150, mViewWeight=50;

    public IosColumnBrightnessView(Context context) {
        super(context);
        initial(context);
    }

    public IosColumnBrightnessView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mTextSize = sp2px(context,mTextSize);
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.IosColumnBrightnessView);
        mColorBackground = typedArray.getColor(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setColorBackground,mColorBackground);
        mColorLoud = typedArray.getColor(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setColorBright,mColorLoud);
        mRXY = typedArray.getDimension(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setRadiusXY, mRXY);
        mTextSize = typedArray.getDimension(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setTextSize,mTextSize);
        mTextColor = typedArray.getColor(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setTextColor,mTextColor);
        mTextHeight = typedArray.getInt(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setTextHeight,mTextHeight);
        mIsDrawTextVolume = typedArray.getBoolean(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setIsDrawTextBright,mIsDrawTextVolume);
        mIsDrawDrawableVolume = typedArray.getBoolean(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setIsDrawDrawableBright,mIsDrawDrawableVolume);
        mColorVolume = typedArray.getColor(R.styleable.IosColumnBrightnessView_iosColumnBrightnessView_setBrightnessColor, mColorVolume);
        typedArray.recycle();

        initial(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mRectBrightnessDrawableMargin = MeasureSpec.getSize(widthMeasureSpec)/10;
        //固定组件高度长度,这里不做适配,可自行修改
        setMeasuredDimension(dp2px(mContext,mViewWeight),dp2px(mContext,mViewHeight));
    }

    private void initial(Context context){
        mContext=context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mCurrentDrawBrightnessRate = getCalculateBrightnessRate();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mRectF = new RectF();
        setWillNotDraw(false);
        setBackgroundColor(Color.TRANSPARENT);
        mPaint.setTextSize(mTextSize);
        getPermission();
        stopAutoBrightness(mContext);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                mDownY=event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                mMoveDistance = mDownY - event.getY();
                calculateLoudRate();
                mDownY=event.getY();
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        refreshAll();
        return true;
    }

    /**
     * 更新所有内容-ui-系统亮度
     */
    private void refreshAll(){
        setSystemBrightness((int)(mCurrentDrawBrightnessRate * mMaxBrightness));
        refreshUI();
    }
    /**
     * 刷新UI
     */
    public void refreshUI(){
        invalidate();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
        onDrawBackground(canvas); //画背景
        onDrawFront(canvas); //画当前亮度前景表示当前多大亮度
        onDrawText(canvas); //画文字
        onDrawSunCircle(canvas);//画底部图标圆心
        canvas.restoreToCount(layerId);
    }
    /**
     * 计算手指移动后亮度UI占比大小,视其为亮度大小
     */
    private void calculateLoudRate(){
        mCurrentDrawBrightnessRate = ( getHeight() * mCurrentDrawBrightnessRate + mMoveDistance) /  getHeight();
        if(mCurrentDrawBrightnessRate >=1){
            mCurrentDrawBrightnessRate =1;
        }
        if(mCurrentDrawBrightnessRate <=0){
            mCurrentDrawBrightnessRate =0;
        }
    }
    /**
     * 画圆弧背景
     * @param canvas
     */
    private void onDrawBackground(Canvas canvas){
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mColorBackground );
        mRectF.left=0;
        mRectF.top=0;
        mRectF.right=canvas.getWidth();
        mRectF.bottom=canvas.getHeight();
        canvas.drawRoundRect(mRectF,mRXY,mRXY,mPaint);
    }
    /**
     * 画亮度背景-方形-随手势上下滑动而变化用来显示亮度大小
     * @param canvas
     */
    private void onDrawFront(Canvas canvas){
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        mPaint.setColor(mColorLoud);
        mRectF.left=0;
        mRectF.top=(canvas.getHeight()-(int)(canvas.getHeight() * mCurrentDrawBrightnessRate));
        mRectF.right=canvas.getWidth();
        mRectF.bottom=canvas.getHeight();
        canvas.drawRect(mRectF,mPaint);
        mPaint.setXfermode(null);
    }
    /**
     * 画文字-展示当前语音大小
     * @param canvas
     */
    private void onDrawText(Canvas canvas){
        if(mIsDrawTextVolume) { //如果开启了则开始绘制
            mPaint.setStyle(Paint.Style.FILL);
            mTextLoud = "" + (int) (mCurrentDrawBrightnessRate * 100);
            mPaint.setColor(mTextColor);
            canvas.drawText(mTextLoud, (canvas.getWidth() / 2 - mPaint.measureText(mTextLoud) / 2), mTextHeight >= 0 ? mTextHeight : getHeight() / 6, mPaint);
        }
    }
    /**
     * 画亮度图标-太阳圆心
     */
    private void onDrawSunCircle(Canvas canvas){
        if(mIsDrawDrawableVolume){ //如果开启了则开始绘制
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(mRectBrightnessDrawableWidth);
            mPaint.setColor(mColorVolume);
            mCircleMaxRadius = (float) (Math.sqrt(canvas.getWidth()) * 1.5);
            mCircleMinRadius = (float) (Math.sqrt(canvas.getWidth()) * 1);
            mCircleMaxWidth = (float) mCurrentDrawBrightnessRate * (mCircleMaxRadius-mCircleMinRadius)+mCircleMinRadius;
            canvas.drawCircle(canvas.getWidth()/2,(float) (canvas.getHeight()*0.8- mRectBrightnessDrawableMargin), mCircleMaxWidth,mPaint);
            onDrawSunRays(canvas,canvas.getWidth()/2,(float) (canvas.getHeight()*0.8- mRectBrightnessDrawableMargin));
        }
    }

    /**
     * 画亮度图标-太阳光芒
     */
    private void onDrawSunRays(Canvas canvas,float cx,float cy){
        mPaint.setStrokeCap(Paint.Cap.ROUND); // 定义线段断电形状为圆头
        //绘制时刻度
        canvas.translate(cx,cy);
        for (int i = 0; i < 10; i++) {
            canvas.drawLine(mCircleMaxWidth, mCircleMaxWidth, (float)(mCircleMaxWidth+5* mCurrentDrawBrightnessRate),(float)( mCircleMaxWidth+5* mCurrentDrawBrightnessRate), mPaint);
            canvas.rotate(36);
        }

    }

    /**
     * 监听view视图在window里时,监听系统亮度
     */
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if(mContext != null) {
            mBrightnessObserver = new BrightnessObserver(mContext, new Handler(Looper.getMainLooper()));
        }

    }
    /**
     * 监听view视图从window里抽离的时,取消广播的注册
     */
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if(null != mBrightnessObserver) {
            mBrightnessObserver.unregister();
        }
    }

    /**
     * 监听亮度改变
     */
    private class BrightnessObserver extends ContentObserver {
        private Context mContext;
        public BrightnessObserver(Context context, Handler handler) {
            super(handler);
            this.mContext =context;
            register();
        }
        //注册监听
        public void register(){
            Uri brightnessUri = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
            mContext.getContentResolver().registerContentObserver(brightnessUri, true,this);
        }
        //取消注册监听
        public void unregister(){
            mContext.getContentResolver().unregisterContentObserver(this);
        }
        @Override
        public void onChange(boolean selfChange) {
            //selfChange 一直是false,无法区分是自己手动改变还是通过系统设置调节,有bug。
            super.onChange(selfChange);
        }
    }

    /**
     * 改变当前系统亮度
     * @return
     */
    public void setSystemBrightness(int brightness) {
        if(null != mContext) {
            if(brightness>=mMaxBrightness){
                brightness=mMaxBrightness;
            }
            if(brightness<=0){
                brightness=0;
            }
                Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,brightness);
        }
    }
    /**
     * 获取当前系统亮度
     * @return
     */
    public int getSystemBrightness(){
        if(null != mContext) {
            try {
              return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
            }

        }
        return 0;
    }
    /**
     * 计算亮度比例
     */
    private double getCalculateBrightnessRate(){
        return (double) getSystemBrightness()/ mMaxBrightness;
    }
    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    /**
     * 将sp值转换为px值,保证文字大小不变
     */
    public int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
    /**
     *
     */
    private void getPermission(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.System.canWrite(mContext)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                intent.setData(Uri.parse("package:" + mContext.getPackageName()));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mContext.startActivity(intent);
            } else {
                // 申请权限后做的操作
            }
        }
    }
    /**
     * 停止自动亮度调节
     */
    private void stopAutoBrightness(Context context) {
        Settings.System.putInt(context.getContentResolver(),
                Settings.System.SCREEN_BRIGHTNESS_MODE,
                Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
    }


}




Android技术生活交流

q群


Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐