[Android] [Android] custom fillet image. You can set whether any corner is fillet in xml
This blog has been included in my android development summary - Click [Android development summary]
- This blog has a reference blog[ android customize a fillet ImageView]
- Compared with the original blog, this blog has the following improvements:
1. You can set whether any of the four corners is a fillet in xml.
2. Change px to dp.
2. Add principle description.
The revised code is as follows:
1. In the values folder, create a new attrs.xml resource file.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="C2RoundAngleImageView">
<attr name="roundWidth2" format="dimension" />
<attr name="roundHeight2" format="dimension" />
<attr name="leftUpCorner" format="boolean" />
<attr name="rightUpCorner" format="boolean" />
<attr name="leftDownCorner" format="boolean" />
<attr name="rightDownCorner" format="boolean" />
</declare-styleable>
</resources>
2. Customize the View.
public class C2RoundAngleImageView extends ImageView {
private Paint paint;
private int roundWidth = 10;
private int roundHeight = 10;
private boolean rightUpCorner = true;
private boolean leftUpCorner = true;
private boolean rightDownCorner = true;
private boolean leftDownCorner = true;
private Paint paint2;
private static Context context;
public C2RoundAngleImageView(Context context) {
super(context);
init(context, null);
}
public C2RoundAngleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public C2RoundAngleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
this.context = context;
if(attrs != null) {
//Point1
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.C2RoundAngleImageView);
roundWidth= a.getDimensionPixelSize(R.styleable.C2RoundAngleImageView_roundWidth2, roundWidth);
roundHeight= a.getDimensionPixelSize(R.styleable.C2RoundAngleImageView_roundHeight2, roundHeight);
rightUpCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_rightUpCorner,true);
rightDownCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_rightDownCorner,true);
leftUpCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_leftUpCorner,true);
leftDownCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_leftDownCorner,true);
}else {
//Point2
float density = context.getResources().getDisplayMetrics().density;
roundWidth = (int) (roundWidth*density);
roundHeight = (int) (roundHeight*density);
}
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
//Point3
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
paint2 = new Paint();
paint2.setXfermode(null);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void draw(Canvas canvas) {
//Point4
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
try {
Canvas canvas2 = new Canvas(bitmap);
//Point5
super.draw(canvas2);
if(leftUpCorner){
//Point6
drawLiftUp(canvas2);
}
if(leftDownCorner){
drawLiftDown(canvas2);
}
if(rightUpCorner){
drawRightUp(canvas2);
}
if(rightDownCorner){
drawRightDown(canvas2);
}
//Point7
canvas.drawBitmap(bitmap, 0, 0, paint2);
bitmap.recycle();
} catch (Throwable e) {
e.printStackTrace();
}
}
private void drawLiftUp(Canvas canvas) {
Path path = new Path();
path.moveTo(0, roundHeight);
path.lineTo(0, 0);
path.lineTo(roundWidth, 0);
path.arcTo(new RectF(
0,
0,
roundWidth * 2,
roundHeight * 2),
-90,
-90);
path.close();
canvas.drawPath(path, paint);
}
private void drawLiftDown(Canvas canvas) {
Path path = new Path();
path.moveTo(0, getHeight()-roundHeight);
path.lineTo(0, getHeight());
path.lineTo(roundWidth, getHeight());
path.arcTo(new RectF(
0,
getHeight()-roundHeight*2,
0+roundWidth*2,
getHeight()),
90,
90);
path.close();
canvas.drawPath(path, paint);
}
private void drawRightDown(Canvas canvas) {
Path path = new Path();
path.moveTo(getWidth()-roundWidth, getHeight());
path.lineTo(getWidth(), getHeight());
path.lineTo(getWidth(), getHeight()-roundHeight);
path.arcTo(new RectF(
getWidth()-roundWidth*2,
getHeight()-roundHeight*2,
getWidth(),
getHeight()), 0, 90);
path.close();
canvas.drawPath(path, paint);
}
private void drawRightUp(Canvas canvas) {
Path path = new Path();
path.moveTo(getWidth(), roundHeight);
path.lineTo(getWidth(), 0);
path.lineTo(getWidth()-roundWidth, 0);
path.arcTo(new RectF(
getWidth()-roundWidth*2,
0,
getWidth(),
0+roundHeight*2),
-90,
90);
path.close();
canvas.drawPath(path, paint);
}
}
- Point1: receive the parameters set in xml here.
- Point2: convert px to dp here.
- Point3: set the Xfermode type of the brush to porterduff.mode.dst'ou out, which can be understood as drawing the source image where there is no intersection
- Point4: create a Bitmap object that can be modified according to the size of canvas.
- Point5: create a canvas of canvas2 according to the bitmap object, and let the View drawn to the canvas be drawn to the bitmap of canvas2. See the source code:
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
/*
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
*
* 1. Draw the background
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. Draw view's content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
*/
... ...
}
- Point6: draw a Path closed Path to be cut in the upper left corner, and make Xfermode processing with the canvas to cut out the fillet. The contour of bitmap changes with canvas 2.
- Point7: draw the bitmap with the rounded corners to the canvas canvas to be displayed.
3. Used in xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:round="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<!-- List pictures -->
<com.example.weihy.mygithubproject.C2RoundAngleImageView
android:id="@+id/c2lamp_recipe_img"
android:layout_width="300dp"
android:layout_height="160dp"
android:scaleType="centerCrop"
android:src="@drawable/coffee"
round:leftUpCorner="false"
round:rightDownCorner="false"
round:roundHeight2="50dp"
round:roundWidth2="50dp"
/>
</LinearLayout>