After the upgrade of the tablet, we found that in the new IOS system, the volume-adjusting controls appearing after the scroll make people look very comfortable, good, try to achieve the following on Android.
Above:
The end result is this.
Ideas for implementation:
First, draw a rectangle.
Step 2, draw a rounded rectangle on top of the rectangle and pass through the
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
Method to make the overlap transparent.
Finally, the first rectangle drawn is manipulated in the code to achieve the effect shown above.
Extensions to controls:
<attr name="bgColor" format="color|integer"></attr>
<attr name="radius" format="integer"></attr>
<attr name="isWrappeLine" format="boolean"></attr>
In the code, add
public void setValues(float v){
......
}
public IphoneSwitchView setColor(int color){
......
}
Two methods allow us to dynamically change the background color of the control.
A callback was added to facilitate subsequent development.
public void registerCallback(ValueChangeCallback callback){
mCallback = callback;
}
interface ValueChangeCallback{
void onValueChanged(double value);
}
Finally, stick the key code:
public class IphoneSwitchView extends View{
private int mWidth,mHeight;
private int strokenWidth;
private boolean isWrapperLine;
private float lastX,lastY,curX,curY;
private int mCurrValue=100,mLastValue=0;
private int curPoint;
private int mBgColor;
private Paint paint;
private ValueChangeCallback mCallback;
public IphoneSwitchView(Context context) {
this(context,null);
}
public IphoneSwitchView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public IphoneSwitchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mWidth = getWidth();
mHeight = getHeight();
//Initialize radian size
strokenWidth = strokenWidth!=-1?strokenWidth:mWidth/5;
}
private void init(Context context,AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.IphoneSwitchView);
int color = (int) array.getInt(R.styleable.IphoneSwitchView_bgColor,-1);
mBgColor = color!=-1?color:getResources().getColor(R.color.colorAccent);
strokenWidth = (int) array.getInt(R.styleable.IphoneSwitchView_radius,-1);
isWrapperLine = array.getBoolean(R.styleable.IphoneSwitchView_isWrappeLine,true);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(4);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw a rectangle at the bottom
RectF rectF = new RectF(0,mHeight-mCurrValue,mWidth,mHeight);
int layerId = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);
paint.setColor(mBgColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(rectF,paint);
// Start drawing rounded rectangle
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(strokenWidth);
rectF = new RectF(0,0,mWidth,mHeight);
canvas.drawRoundRect(rectF,strokenWidth,strokenWidth,paint);
paint.setXfermode(null);
canvas.restoreToCount(layerId);
// Determine whether an outer border is required
if(isWrapperLine){
paint.setStrokeWidth(2);
paint.setColor(Color.BLACK);
rectF = new RectF(1,1,mWidth-1,mHeight-1);
canvas.drawRoundRect(rectF,strokenWidth,strokenWidth,paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = event.getX();
lastY = event.getY();
//Remember to do event interception consumer action
return true;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
resetValues(lastY-curY);
lastX = event.getX();
lastY = event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(event);
}
private void resetValues(float v) {
float cacheValue = mCurrValue+v;
Log.d("chenxiaoping","v := "+v+" "+cacheValue+" mHeight "+mHeight);
if(cacheValue<=mHeight&&cacheValue>=0){
mCurrValue = (int) cacheValue;
if(mCallback!=null){
mCallback.onValueChanged(cacheValue/mHeight);
}
}
postInvalidate();
}
public void setValues(float v){
setInitialValue(v);
}
public IphoneSwitchView setColor(int color){
mBgColor = color;
postInvalidate();
return this;
}
/**
* persent 0-1
* @param value
* @return
*/
public IphoneSwitchView setInitialValue(double value){
if(value>1||value<0){
mCurrValue = 0;
}else{
mCurrValue = (int) (mHeight*value);
}
if(mCallback!=null){
mCallback.onValueChanged(mCurrValue/mHeight);
}
mLastValue = mCurrValue;
postInvalidate();
return this;
}
public void registerCallback(ValueChangeCallback callback){
mCallback = callback;
}
interface ValueChangeCallback{
void onValueChanged(double value);
}
}
After the introduction, continue your efforts.