These days when I read the code of Google's native CameraApp, what I have to say is the complexity of the real TM, especially the logical processing part. About the native CameraApp of google, which may be written as a new series in the future, today I mainly introduce the implementation of a custom View that I see online!!
Still the old rule, let's see what happens first!!
Take a look at the detailed code for this custom 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;//Click Hot Spot
private int cur_sections = 2;
private ResponseOnTouch responseOnTouch;
private int bitMapHeight = 38;//The first point starts at 76, so take half the distance
private int textMove = 60;//The distance between the font and the lower point, because the font size is 40px plus 10 spacing
private int[] colors = new int[]{0xffdf5600,0x33000000};//Orange progress bar, grey progress bar, grey font
private int textSize;
private int circleRadius;
private ArrayList<String> 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;
}
/**
* Called after instantiation to set the number of segments and text for bar
*/
public void initData(ArrayList<String> section){
if(section != null){
section_title = section;
}else {
String[] str = new String[]{"low", "in", "high"};
section_title = new ArrayList<String>();
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();
}
}
First of all, I declare that this view was not written by myself, but by another blogger. I have modified the code of his click event handling (actually about which click between two values to choose). If you are interested, you can see the code. This custom view is still relatively simple to implement!!
When you have this custom view, you need to call the initData method in your code to initialize the scale values on the seekBar!!This feels a little strange. Why not put it in an attribute?Interested friends can modify the code to initialize scale value in custom attributes!!!
There's nothing to say about other aspects of using this View, just like using other views!!
Okay, let's just say a little about this custom View. Interested friends can follow me. What can we talk about together?!