要实现的效果图如下:
实现此效果的第一思路是使用Path 和canvas实现,path来规定平行四边形。
实现如下
布局文件
package com.whuthm.imageshape;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class TestView extends ImageView {
public TestView(Context context) {
this(context, null);
}
public TestView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TestView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
Drawable d = getResources().getDrawable(R.drawable.image1);
d.setBounds(0, 0, width, height);
canvas.save();
//一个平行四边形
Path path = new Path();
path.moveTo(100, 0);
path.lineTo(0, height);
path.lineTo(width - 100, height);
path.lineTo(width, 0);
canvas.clipPath(path);
//将图像画在canvas上
d.draw(canvas);
canvas.restore();
}
}
效果实现,但是一个很严重的问题是锯齿很严重,而且对paint,bitmapshader,或者canvas使用抗锯齿也无效。效果图如下:
另一种解决方法是,使用ShapeDrawable
方法:根据ImageView的drawable创建一个shapedrawable,并设置shapedrawable的shape, 然后在ondraw方法中设置位图渲染,设置区域,然后将shapedrawable画在canvas上。
布局文件
package com.whuthm.imageshape;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.Shape;
import android.util.AttributeSet;
import android.widget.ImageView;
public class ShapeImageView extends ImageView {
public static final String TAG = "ShapeImageView";
private ShapeDrawable mShapeDrawable;
private Shape mShape;
private boolean mIsShape;
private boolean mRebuildShape;
public ShapeImageView(Context context) {
this(context, null);
}
public ShapeImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ShapeImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
//设置shape
public void setShap(Shape shape) {
mShape = shape;
mIsShape = true;
mRebuildShape = true;
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
if (mIsShape) {
//获取ImageView的drawble,当调用过setShape方法时,走下面的流程
Drawable oldDrawable = getDrawable();
if (oldDrawable == null || mShape == null) {
return;
}
Rect bounds = oldDrawable.getBounds();
if (bounds == null || bounds.width() == 0 || bounds.height() == 0) {
return;
}
if (mShapeDrawable == null) {
mShapeDrawable = new ShapeDrawable();
}
//设置shapedrawable的bounds
mShapeDrawable.setBounds(bounds);
if (mRebuildShape) {
mRebuildShape = false;
//获取bitmap
Bitmap bm = drawableToBitmap(oldDrawable);
if (bm == null) {
return;
}
//创建一个bitmapshader,shapedrawable设置这个位图渲染
BitmapShader bitmapShader = new BitmapShader(bm,
TileMode.CLAMP, TileMode.CLAMP);
mShapeDrawable.getPaint().setFlags(Paint.ANTI_ALIAS_FLAG);
mShapeDrawable.getPaint().setStyle(Paint.Style.FILL);
mShapeDrawable.getPaint().setShader(bitmapShader);
mShapeDrawable.setShape(mShape);
}
//当时平行四边形时设置Shape的所在区域
if (mShape instanceof ParallelogramShape) {
((ParallelogramShape) mShape).setRect(bounds);
}
int paddingTop = getPaddingTop();
int paddingLeft = getPaddingLeft();
// int paddingRight = getPaddingRight();
// int paddingBottom = getPaddingBottom();
// Matrix imageMatrix = getImageMatrix();
// int left = getLeft();
// int top = getTop();
// int right = getRight();
// int bottom = getBottom();
//将mShapeDrawable画在canvas
if (paddingTop == 0 && paddingLeft == 0) {
mShapeDrawable.draw(canvas);
} else {
int saveCount = canvas.getSaveCount();
canvas.save();
canvas.translate(paddingLeft, paddingTop);
mShapeDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
}
} else {
super.onDraw(canvas);
}
}
//此方法用于创建一个bitmap
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null || drawable.getBounds() == null) {
return null;
}
// if (drawable instanceof BitmapDrawable) {
// return ((BitmapDrawable) drawable).getBitmap();
// }
Bitmap bitmap;
int width = drawable.getBounds().width();
int height = drawable.getBounds().height();
try {
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.draw(canvas);
} catch (IllegalArgumentException e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
}
package com.whuthm.imageshape;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.shapes.Shape;
public class ParallelogramShape extends Shape {
Path path;
Rect rect;
int offset;
float scale = -1f;
ParallelogramShape() {
path = new Path();
}
public void setRect(Rect rect) {
this.rect = rect;
}
public void setOffset(int offset) {
this.offset = offset;
}
public void setScale(float scale) {
this.scale = scale;
}
//此方法设置path,path为平行四边形
@Override
public void draw(Canvas canvas, Paint paint) {
if (rect == null || rect.width() <= 0 || rect.height() <= 0) {
return;
}
if (scale > 0.0f && scale < 1.0f) {
offset = (int) (scale * rect.width());
}
path.reset();
path.moveTo(offset, rect.left);
path.lineTo(rect.left, rect.bottom);
path.lineTo(rect.right - offset, rect.bottom);
path.lineTo(rect.right, 0);
canvas.drawPath(path, paint);
}
}
package com.whuthm.imageshape;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个平行四边形的shape
ParallelogramShape shape = new ParallelogramShape();
shape.setScale(0.2f);
((ShapeImageView) findViewById(R.id.image1)).setShap(shape);
}
}
代码链接