平行四邊形的效果實現

要實現的效果圖如下:



實現此效果的第一思路是使用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>


TestView類實現

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);

    }

}

效果圖如下:





代碼鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章