答案 0 :(得分:2)
你可以在git中引用流动抽屉
链接:https://github.com/mxn21/FlowingDrawer
在此示例中,他们使用“LeftDrawerLayout”自定义类来处理此效果,其属性由FlowingView设置。
使用此选项创建自定义类。
答案 1 :(得分:0)
这是我的解决方案的原型:
我创建了自定义FrameLayout
并覆盖onDraw
方法。这就是它的样子:
我会很快添加评论和说明,它是如何工作的!
public class CurvedFrameLayout extends FrameLayout {
private Paint paint;
private Path path;
private int width;
private int height;
private float leftCurvePosition = 0.5f;
private float topCurvePosition = 0.5f;
private float rightCurvePosition = 0.5f;
private float bottomCurvePosition = 0.5f;
private int minimumCurve = 50;
private int maximumCurve = 100;
private int minimumLeftCurve = minimumCurve;
private int minimumTopCurve = minimumCurve;
private int minimumRightCurve = minimumCurve;
private int minimumBottomCurve = minimumCurve;
private int maximumLeftCurve = maximumCurve;
private int maximumTopCurve = maximumCurve;
private int maximumRightCurve = maximumCurve;
private int maximumBottomCurve = maximumCurve;
private float leftCurveOffset = 0f;
private float topCurveOffset = 0f;
private float rightCurveOffset = 0f;
private float bottomCurveOffset = 0f;
private int curveRadius = 150;
private float elevation = 4f;
private float cornerRadius = 50f;
private float margin = elevation;
private int color = Color.LTGRAY;
public CurvedFrameLayout(Context context) {
super(context);
init(context, null);
}
public CurvedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CurvedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.CurvedFrameLayout,
0, 0);
try {
leftCurvePosition = a.getFloat(R.styleable.CurvedFrameLayout_leftCurvePosition, 0.5f);
topCurvePosition = a.getFloat(R.styleable.CurvedFrameLayout_topCurvePosition, 0.5f);
rightCurvePosition = a.getFloat(R.styleable.CurvedFrameLayout_rightCurvePosition, 0.5f);
bottomCurvePosition = a.getFloat(R.styleable.CurvedFrameLayout_bottomCurvePosition, 0.5f);
minimumCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_minimumCurve, 50);
maximumCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_maximumCurve, 100);
minimumLeftCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_minimumLeftCurve, 50);
minimumTopCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_minimumTopCurve, 50);
minimumRightCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_minimumRightCurve, 50);
minimumBottomCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_minimumBottomCurve, 50);
maximumLeftCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_maximumLeftCurve, 100);
maximumTopCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_maximumTopCurve, 100);
maximumRightCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_maximumRightCurve, 100);
maximumBottomCurve = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_maximumBottomCurve, 100);
leftCurveOffset = a.getFloat(R.styleable.CurvedFrameLayout_leftCurveOffset, 0f);
topCurveOffset = a.getFloat(R.styleable.CurvedFrameLayout_topCurveOffset, 0f);
rightCurveOffset = a.getFloat(R.styleable.CurvedFrameLayout_rightCurveOffset, 0f);
bottomCurveOffset = a.getFloat(R.styleable.CurvedFrameLayout_bottomCurveOffset, 0f);
curveRadius = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_curveRadius, 150);
cornerRadius = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_cornerRadius, 50);
elevation = a.getDimensionPixelSize(R.styleable.CurvedFrameLayout_elevation, 0);
margin = elevation;
color = a.getColor(R.styleable.CurvedFrameLayout_color, Color.LTGRAY);
} finally {
a.recycle();
}
}
setWillNotDraw(false);
paint = new Paint();
//setLayerType(LAYER_TYPE_SOFTWARE, paint);
paint.setColor(color);
paint.setShadowLayer(elevation, 0f, 0f, Color.LTGRAY);
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawLayout(canvas);
}
private void drawLayout(Canvas canvas) {
float cornerRadiusMargin = cornerRadius + margin;
float widthMinusMargin = width - margin;
float widthMinusMarginMinusCornerR = widthMinusMargin - cornerRadius;
float heightMinusMargin = height - margin;
float heightMinusMarginMinusCornerR = heightMinusMargin - cornerRadius;
//Top-left corner
path.reset();
path.moveTo(margin, cornerRadiusMargin);
path.quadTo(margin, margin, cornerRadiusMargin, margin);
//Top line
drawTopEdge(cornerRadiusMargin, margin, widthMinusMarginMinusCornerR, margin);
//Top-right corner
path.quadTo(widthMinusMargin, margin, widthMinusMargin, cornerRadiusMargin);
//Right line
drawRightEdge(widthMinusMargin, cornerRadiusMargin, widthMinusMargin, heightMinusMarginMinusCornerR);
//Bottom-right corner
path.quadTo(widthMinusMargin, heightMinusMargin, widthMinusMarginMinusCornerR, heightMinusMargin);
//Bottom line
path.lineTo(cornerRadiusMargin, heightMinusMargin);
//Bottom-left corner
path.quadTo(margin, heightMinusMargin, margin, heightMinusMarginMinusCornerR);
//Left line
drawLeftEdge(margin, heightMinusMarginMinusCornerR, margin, cornerRadiusMargin);
canvas.drawPath(path, paint);
canvas.clipPath(path, Region.Op.REPLACE);
}
private void drawTopEdge(float x1, float y1, float x2, float y2) {
float curveCenterX = (x1 + x2) * topCurvePosition;
float curveDeltaY = positionForOffset(minimumTopCurve, maximumTopCurve, topCurveOffset);
int curveX = curveRadius / 2;
path.lineTo(curveCenterX - curveRadius, y1);
path.rCubicTo(curveX, 0, curveX, curveDeltaY, curveRadius, curveDeltaY);
path.rCubicTo(curveX, 0, curveX, -curveDeltaY, curveRadius, -curveDeltaY);
path.lineTo(x2, y2);
}
private void drawRightEdge(float x1, float y1, float x2, float y2) {
float curveCenterY = (y1 + y2) * rightCurvePosition;
float curveDeltaX = positionForOffset(minimumRightCurve, maximumRightCurve, rightCurveOffset);
path.lineTo(x1, curveCenterY - curveRadius);
int curveY = curveRadius / 2;
path.rCubicTo(0, curveY, -curveDeltaX, curveY, -curveDeltaX, curveRadius);
path.rCubicTo(0, curveY, curveDeltaX, curveY, curveDeltaX, curveRadius);
path.lineTo(x2, y2);
}
private void drawLeftEdge(float x1, float y1, float x2, float y2) {
float curveCenterY = (y1 + y2) * leftCurvePosition;
float curveDeltaX = positionForOffset(minimumLeftCurve, maximumLeftCurve, leftCurveOffset);
path.lineTo(x1, curveCenterY + curveRadius);
int curveY = -curveRadius / 2;
path.rCubicTo(0, curveY, curveDeltaX, curveY, curveDeltaX, -curveRadius);
path.rCubicTo(0, curveY, -curveDeltaX, curveY, -curveDeltaX, -curveRadius);
path.lineTo(x2, y2);
}
private float positionForOffset(float start, float end, float offset) {
return start + (end - start) * offset;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
}
public void setLeftCurveOffset(float leftCurveOffset) {
this.leftCurveOffset = leftCurveOffset;
invalidate();
}
public void setRightCurveOffset(float rightCurveOffset) {
this.rightCurveOffset = rightCurveOffset;
invalidate();
}
}
目前,代码并不完美,但只要我改进此代码,我就会更新答案。