要實現的效果圖如下:
實現此效果的第一思路是使用Path 和canvas實現,path來規定平行四邊形。
實現如下
佈局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.whuthm.imageshape.TestView
android:layout_width="250dp"
android:layout_height="150dp"
android:layout_centerInParent="true"/>
</RelativeLayout>
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上。
佈局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.whuthm.imageshape.ShapeImageView
android:id="@+id/image1"
android:layout_width="250dp"
android:layout_height="150dp"
android:layout_centerInParent="true"
android:scaleType="fitXY"
android:src="@drawable/image1" />
<com.whuthm.imageshape.ShapeImageView
android:id="@+id/image2"
android:layout_width="250dp"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="@drawable/image2" />
</RelativeLayout>
關鍵類ShapeImageView
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;
}
}
平行四邊形shape :ParallelogramShape
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);
}
}
activity如下:
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);
}
}
效果圖如下: