这几天在看google原生CameraApp的代码,不得不说写的是真TM的复杂,特别是逻辑处理那一块,关于google原生CameraApp这一块后续可能会作为一个新的系列来写,今天主要介绍我在网上看到的关于一个自定义View的实现!!
还是老规矩,我们先看一下实现的效果!!
下面看一下这个自定义的SeekBar的详细代码:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class CustomSeekBar extends View {
private final String TAG = "CustomSeekBar";
private int width;
private int height;
private int downX = 0;
private int downY = 0;
private int upX = 0;
private int upY = 0;
private int moveX = 0;
private int moveY = 0;
private float scale = 0;
private int perWidth = 0;
private Paint mPaint;
private Paint mTextPaint;
private Paint buttonPaint;
private Canvas canvas;
private Bitmap bitmap;
private Bitmap thumb;
private Bitmap spot;
private Bitmap spot_on;
private int hotarea = 100;//点击的热区
private int cur_sections = 2;
private ResponseOnTouch responseOnTouch;
private int bitMapHeight = 38;//第一个点的起始位置起始,图片的长宽是76,所以取一半的距离
private int textMove = 60;//字与下方点的距离,因为字体字体是40px,再加上10的间隔
private int[] colors = new int[]{0xffdf5600,0x33000000};//进度条的橙色,进度条的灰色,字体的灰色
private int textSize;
private int circleRadius;
private ArrayList section_title;
public interface ResponseOnTouch{
void onTouchResponse(int progress);
}
public CustomSeekBar(Context context) {
super(context);
}
public CustomSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
cur_sections = 0;
thumb = getDotBitmap(48,48,Color.BLACK);
spot = getDotBitmap(16,16,Color.GRAY);
spot_on = getDotBitmap(16,16,Color.RED);
bitMapHeight = thumb.getHeight()/2;
textMove = bitMapHeight+22;
textSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
circleRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(3);
mTextPaint = new Paint(Paint.DITHER_FLAG);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(textSize);
mTextPaint.setColor(0xffb5b5b4);
buttonPaint = new Paint(Paint.DITHER_FLAG);
buttonPaint.setAntiAlias(true);
}
private Bitmap getDotBitmap(int width,int height,int color){
Bitmap b = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
paint.setStyle(Paint.Style.FILL);
Canvas c = new Canvas(b);
c.drawCircle(width/2,height/2,Math.min(width/2,height/2),paint);
return b;
}
/**
* 实例化后调用,设置bar的段数和文字
*/
public void initData(ArrayList section){
if(section != null){
section_title = section;
}else {
String[] str = new String[]{"低", "中", "高"};
section_title = new ArrayList();
for (int i = 0; i < str.length; i++) {
section_title.add(str[i]);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
width = widthSize;
float scaleX = widthSize / 1080;
float scaleY = heightSize / 1920;
scale = Math.max(scaleX,scaleY);
height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics());
setMeasuredDimension(width, height);
width = width-bitMapHeight/2;
perWidth = (width - section_title.size()*spot.getWidth() - thumb.getWidth()/2) / (section_title.size()-1);
hotarea = perWidth/2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAlpha(0);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setAlpha(255);
mPaint.setColor(colors[1]);
canvas.drawLine(bitMapHeight, height * 2 / 3, width - bitMapHeight - spot_on.getWidth() / 2, height * 2 / 3, mPaint);
int section = 0;
while(section < section_title.size()){
if(section < cur_sections) {
mPaint.setColor(colors[0]);
canvas.drawLine(thumb.getWidth()/2 + section * perWidth + (section+1) * spot_on.getWidth(),height * 2 / 3,
thumb.getWidth()/2 + section * perWidth + (section+1) * spot_on.getWidth() + perWidth,height * 2 / 3,mPaint);
canvas.drawBitmap(spot_on, thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(),height * 2 / 3 - spot_on.getHeight()/2,mPaint);
}else{
mPaint.setAlpha(255);
if(section == section_title.size()-1){
canvas.drawBitmap(spot, width - spot_on.getWidth() - bitMapHeight/2, height * 2 / 3 - spot.getHeight() / 2, mPaint);
}else {
canvas.drawBitmap(spot, thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(), height * 2 / 3 - spot.getHeight() / 2, mPaint);
}
}
if(section == section_title.size()-1) {
canvas.drawText(section_title.get(section), width - spot_on.getWidth()- bitMapHeight/4 - textSize / 2, height * 2 / 3 - textMove, mTextPaint);
}else{
canvas.drawText(section_title.get(section), thumb.getWidth()/2 + section * perWidth + section * spot_on.getWidth(), height * 2 / 3 - textMove, mTextPaint);
}
section++;
}
if(cur_sections == section_title.size()-1){
canvas.drawBitmap(thumb, width - spot_on.getWidth() - bitMapHeight/2 - thumb.getWidth() / 2,
height * 2 / 3 - bitMapHeight, buttonPaint);
}else {
canvas.drawBitmap(thumb, thumb.getWidth()/2 + cur_sections * perWidth + cur_sections * spot_on.getWidth() - thumb.getWidth()/4 ,
height * 2 / 3 - bitMapHeight, buttonPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
thumb = getDotBitmap(48,48,Color.BLACK);
moveX = (int) event.getX();
moveY = (int) event.getY();
responseTouch(moveX, moveY);
break;
case MotionEvent.ACTION_UP:
thumb = getDotBitmap(48,48,Color.BLACK);
upX = (int) event.getX();
upY = (int) event.getY();
responseTouch(upX, upY);
responseOnTouch.onTouchResponse(cur_sections);
break;
}
return true;
}
private void responseTouch(int x, int y){
if(x <= width-bitMapHeight/2) {
int section = (x-12)/(perWidth+spot.getWidth())+1;
cur_sections = (x-section*spot.getWidth() + perWidth / 2) / perWidth;
}else{
cur_sections = section_title.size()-1;
}
invalidate();
}
public void setResponseOnTouch(ResponseOnTouch response){
responseOnTouch = response;
}
public void setProgress(int progress){
cur_sections = progress;
invalidate();
}
}
首先在此声明,这个view不是本人写的,是另一位博主的作品,我对他的点击事件处理方面的代码进行了修改(其实就是关于点击在两个值之间到底选择哪一个的问题),有兴趣的话可以看一下代码,这个自定View的实现还是比较简单的!!
在是有这个自定义view的时候,需要我们在代码中调用initData方法去初始化seekBar上的刻度值!!这个感觉有点奇怪,为什么不放在属性里面呢??有兴趣的朋友可以修改一下代码,将刻度值得初始化放在自定义属性中!!!
关于使用这个View的其他方面没有什么好说的,就像使用其他的View一样即可!!
好了,关于这个自定义的View就简单讲到这里,有兴趣的朋友可以关注我一下,有什么问题可以一起交流讨论!!