如图最近项目要做一个剪切音乐的控件,于是打算手写一个。

先分析一下,就是需要两个首尾的拉杆,开始的不能超过结束的,开始的不能低于起点,结束的不能低于开始的也不能高于终点。

package com.lewanjia.dancelog.views;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;import com.lewanjia.dancelog.R;
import com.lewanjia.dancelog.utils.LogUtils;/*** @autor lzj*/
public class CutMusicLineSeekBar extends View {private Paint circlePaint;//private Paint circlePaintOver;//private Paint playPaint;private float mHeight;private float mWidth;//x轴的原点坐标private int xOri;//y轴的原点坐标private int yOri;private Context mContext;private Bitmap dotBitmapStart;private Bitmap dotBitmapEnd;private Drawable dotDrawableEnd;private Drawable dotDrawableStart;private float dotRadius;private float circleB = 0;//半径private final static int VAULE_3 = 3;private final static int VAULE_4 = 4;private float markPointX = 0;private float markPointY = 0;private float markPointXEnd = 0;private float markPointYEnd = 0;private float markPalyX = 0;private int maxProgress = 100;private float pointWidth;private float pointHeight;private float startProcess = 0;private float endProcess = 100;private float palyProcess= 0;public CutMusicLineSeekBar(Context context) {this(context, null);}public CutMusicLineSeekBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CutMusicLineSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.mContext = context;initView(context, attrs, defStyleAttr);}private void initView(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CutMusicCircleSeekBar, defStyleAttr, 0);int count = array.getIndexCount();for (int i = 0; i < count; i++) {int attr = array.getIndex(i);switch (attr) {}}array.recycle();}/*** 初始化画笔*/private void init() {circlePaint = new Paint();circlePaint.setColor(Color.parseColor("#a4a4a4"));circlePaint.setAntiAlias(true);circlePaint.setStyle(Paint.Style.STROKE);// 设置中空的样式circlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿circlePaint.setStrokeWidth(dip2px(mContext, VAULE_4));circlePaintOver = new Paint();circlePaintOver.setColor(Color.parseColor("#33000000"));circlePaintOver.setAntiAlias(true);circlePaintOver.setStyle(Paint.Style.FILL);// 设置中空的样式circlePaintOver.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿circlePaintOver.setStrokeWidth(dip2px(mContext, VAULE_4));playPaint = new Paint();playPaint.setColor(Color.parseColor("#FFAA00"));playPaint.setAntiAlias(true);playPaint.setStyle(Paint.Style.FILL);// 设置中空的样式playPaint.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿playPaint.setStrokeWidth(dip2px(mContext, 1));dotDrawableEnd = mContext.getResources().getDrawable(R.mipmap.image_cut_music_right);dotDrawableStart = mContext.getResources().getDrawable(R.mipmap.image_cut_music_left);if (dotDrawableStart != null) {dotBitmapStart = ((BitmapDrawable) dotDrawableStart).getBitmap();dotBitmapEnd = ((BitmapDrawable) dotDrawableEnd).getBitmap();dotRadius = Math.max(dotRadius, Math.max(dotBitmapStart.getWidth() / 2, dotBitmapStart.getHeight() / 2));circleB = getWidth() / 2 - dip2px(mContext, VAULE_3) - dotBitmapStart.getWidth() / 4;pointWidth = (float) dotBitmapEnd.getWidth();pointHeight = dotBitmapEnd.getHeight();}dotRadius = dotBitmapStart.getWidth() / 2;markPointXEnd = mWidth - pointWidth;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width;int height;int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY) {width = widthSize;} else {width = widthSize * 1 / 2;}if (heightMode == MeasureSpec.EXACTLY) {height = heightSize;} else {height = heightSize * 1 / 2;}setMeasuredDimension(width, height);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);mHeight = getHeight();mWidth = getWidth();xOri = getWidth() / 2;yOri = getHeight() / 2;markPointY = mHeight / 2;markPointYEnd = mHeight / 2;init();}@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawBitmpStart(canvas);canvas.save();}float lastx;float lasty;boolean isOntouch = false;int moveFirst = 0;//0start 1end 2paly@Overridepublic boolean onTouchEvent(MotionEvent event) {isOntouch = true;switch (event.getAction()) {case MotionEvent.ACTION_DOWN:lastx = event.getX();lasty = event.getY();double fisrt = distance(lastx, markPointX);double second = distance(lastx, markPointXEnd);double palyLine = distance(lastx, markPalyX);if (fisrt<=second&&fisrt<=palyLine){moveFirst = 0;}else if (second<=fisrt&&second<=palyLine) {moveFirst = 1;}else if (palyLine<fisrt&&palyLine<=second){moveFirst = 2;}moved(lastx, lasty, false, event, moveFirst);return true;case MotionEvent.ACTION_MOVE:lastx = event.getX();lasty = event.getY();moved(lastx, lasty, false, event, moveFirst);Log.e("", "");return true;case MotionEvent.ACTION_UP:if (moveFirst==2){if (onProcessChangeLister!=null){onProcessChangeLister.changePaly(getPalyProgress());}}return true;
//            case MotionEvent.ACTION_CANCEL:
//                f (moveFirst==2){
//                if (onProcessChangeLister!=null){
//                    onProcessChangeLister.changePaly(getPalyProgress());
//                }
//            }
//            return true;}return false;}private float distance(float x1, float x2) {return (float) Math.abs(x1 - x2);}public int dip2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}/*** @param canvas*/private void drawBitmpStart(Canvas canvas) {canvas.drawBitmap(dotBitmapStart, markPointX, 0, circlePaint);canvas.drawBitmap(dotBitmapEnd, markPointXEnd, 0, circlePaint);
//        circlePaintOverRectF rectF1 = new RectF();rectF1.left = 0;rectF1.right = markPointX;rectF1.top = dip2px(mContext, VAULE_4);rectF1.bottom = mHeight - dip2px(mContext, VAULE_4);RectF rectF2 = new RectF();rectF2.left = markPointXEnd + pointWidth;rectF2.right = mWidth;rectF2.top = dip2px(mContext, VAULE_4);rectF2.bottom = mHeight - dip2px(mContext, VAULE_4);RectF rectF3 = new RectF();rectF3.left = markPalyX + pointWidth;rectF3.right = markPalyX + pointWidth + dip2px(mContext, 2);rectF3.top = dip2px(mContext, VAULE_4);rectF3.bottom = mHeight - dip2px(mContext, VAULE_4);canvas.drawRect(rectF1, circlePaintOver);canvas.drawRect(rectF2, circlePaintOver);canvas.drawRect(rectF3, playPaint);}public void setPalyProgress(float progress){this.palyProcess = progress;markPalyX = (mWidth-pointWidth*2f)* progress/100f;invalidate();}public float getPalyProgress(){palyProcess =markPalyX/(mWidth-pointWidth*2f)*100f;LogUtils.E("456","palyProcess=="+palyProcess);return palyProcess>99.6?100:palyProcess;}public float getStartProgress(){startProcess = markPointX/(mWidth-pointWidth*2f)*100f;return startProcess>99.6?100:startProcess;}public float getEndProgress(){endProcess = (( markPointXEnd - pointWidth)/(mWidth-pointWidth*2f)*100f);return endProcess>99.6?100:endProcess;}public void setStartProgress(float progress){this.startProcess = progress;markPointX = (mWidth-pointWidth*2f)* progress/100f;invalidate();LogUtils.E("456","startProcess=="+startProcess);if (onProcessChangeLister != null) {onProcessChangeLister.changeStart(startProcess);onProcessChangeLister.changeEnd(endProcess);}}public void setEndProgress(float progress){this.endProcess = progress;markPointXEnd = (mWidth-pointWidth*2f)* progress/100f+pointWidth;invalidate();LogUtils.E("456","endProcess=="+endProcess);if (onProcessChangeLister != null) {onProcessChangeLister.changeStart(startProcess);onProcessChangeLister.changeEnd(endProcess);}}private void moved(float x, float y, boolean up, MotionEvent event, int moveFirst) {if (x < 0 || x > mWidth - pointWidth)return;if (moveFirst==0) {if (x >= markPointXEnd - pointWidth)return;markPointX = x;if (markPalyX < markPointX) {markPalyX = markPointX;}} else if (moveFirst==1){if (x <= markPointX + pointWidth)return;markPointXEnd = x;
//            if (markPalyX > markPointXEnd-pointWidth) {
//                markPalyX = markPointXEnd-pointWidth;
//            }}else {if (x >= mWidth - pointWidth*2)return;markPalyX= x;}if (onProcessChangeLister != null) {onProcessChangeLister.changeStart(getStartProgress());onProcessChangeLister.changeEnd(getEndProgress());}invalidate();}private OnProcessChangeLister onProcessChangeLister;public interface OnProcessChangeLister {void changeStart(float process);void changeEnd(float preocess);void changePaly(float preocess);}public void setOnProcessChangeLister(OnProcessChangeLister onProcessChangeLister) {this.onProcessChangeLister = onProcessChangeLister;}public int getMaxProgress() {return maxProgress;}}

代码看起来也不复杂,只要理清逻辑就很简单。如果还需要音乐轨道的波浪图,可以评论

安卓编辑剪切音乐控件相关推荐

  1. 安卓锁屏音乐控件开发

    首先我个人先吐槽一下,这是一个吃力不讨好的活.为什么?因为现在安卓手机的各种定制rom五花八门,各种各样,miui.乐蛙.emui.努比亚...我们今天要做的事情就是要在各种系统的锁屏界面,出现一个音 ...

  2. 可以编辑的标签控件CStatic

    可以编辑的标签控件CStatic,可以使编辑框,组合框,也可以是一个CDateTimeCtrl用来选择时间. 下载地址 http://download.csdn.net/detail/hemmingw ...

  3. 可编辑的日历控件_选择正确的WordPress编辑日历插件

    可编辑的日历控件 什么是编辑日历? (What is an Editorial Calendar?) An editorial calendar is the foundation of strate ...

  4. 编辑任务EditorTask控件为什么不能使用

    编辑任务EditorTask 控件为什么不能使用 EditorTask控件是adf中提供的,它的使用条件是这样的: a 需要使用的是ArcGIS Server Local方式连接的服务 b shape ...

  5. 下载spotify音乐_如何将Google Maps音乐控件用于Spotify,Apple Music或Google Play音乐

    下载spotify音乐 Google Maps now offers built-in music playback controls you can use while navigating. It ...

  6. ExtJs学习笔记(4)_EditorGridPanel(可编辑的网格控件)

    这一节,我们将看到ExtJs功能强大的可编辑网格控件,几乎与VS.Net的GridView功能一样了,但是ExtJs的可是纯JS的UI 一.静态示例(改自ExtJs的官方示例) a.因为我们是采用xm ...

  7. MFC设置静态文本框,编辑框等控件背景和字体颜色

    在MFC类库提供了CWnd::OnCtlColor函数,在工作框架的子窗口被重画时将调用该成员函数.因此可以重载WM_CTLCOLOR消息的响应函数.此函数的原型: afx_msg HBRUSH On ...

  8. 安卓学习 之 UI控件(三)

    一.常用控件 1.TextView(文本) match_parent:控件与父类相同(基本不用fil_parent)wrap_content:刚好包裹里面内容. android:gravity调节文字 ...

  9. 『安卓』安卓开发基础--基本控件

    1. Textview 显示文字,相当于Panel.一般用来文本展示,继承自android.view.View,在android.widget包中. <TextView//控件id androi ...

最新文章

  1. Global.asax中Application_Error无法执行
  2. java类的运行顺序_Java语言类的基本运行顺序
  3. 网易OpenStack部署运维实战
  4. pytorch torch.nn.Sequential(* args)(嘎哈用的?构建神经网络用的?)
  5. linux命令-- pstack命令(跟踪进程栈)
  6. linux-压缩和解压类
  7. (七)HTML和CSS 、JavaScript 和Java到底有什么区别,今天终于明白了!!!
  8. [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流
  9. 插件代码_我们开源了一款 SonarQube iOS 代码扫描插件
  10. 防火墙审计策略和应用场景介绍(USG6307E)
  11. 智能优化算法:世界杯优化算法-附代码
  12. linux上python升级_Linux下安装升级python
  13. 非线性可视化(2)非线性相图
  14. 今天解封了,该递交作业了,我做了个智能机器人
  15. 【CentOS7】启动 CentOS7 系统时卡在开机界面 7 解决办法
  16. 信息学奥赛C++编程:苹果和虫子
  17. 麒麟鲲鹏升腾鸿蒙巴龙,华为四大芯片 麒麟、巴龙、昇腾和鲲鹏“四大天王”...
  18. 新视野大学英语4-UNIT4-Expression in use
  19. python画神经网络结构图_神经网络结构画图
  20. 用计算机怎么算二进制数,计算机上的二进制是怎么算的?(计算机中使用二进制来处理和储存所有的数据“逢二进一”。它使用0和1来表示所有的数。例如:1...

热门文章

  1. 「硬见小百科」41条电路接线方法,每一条都是10+年经验总结
  2. ie7文档模式下:被呼叫方(服务器[不是服务器应用程序])不可用并已消失。所有连接均无效。没有执行呼叫。
  3. 转:一个banner仔的自我修养(1) ——字体字形篇
  4. 名词解释atm网络_网络名词解释
  5. Bug[9] AT+COPS设置网络模式为自动,返回ERROR
  6. C++11标准下的单例设计模式
  7. Mysql 5.7主从
  8. 国家政策!大有广阔天地的商城结算平台
  9. C# SpinLock实现
  10. 汽车电子标识标准呼之欲出