您的位置:首页 > 移动开发 > Android开发

Android-给照片底部添加波浪效果

2015-07-29 13:46 633 查看
实现的效果是酱紫的:



使用方式跟普通的ImageView是一样的,代码:

/**
 * 参考:http://blog.csdn.net/lee576/article/details/7900228
 * */
public class WaveBottomImageView extends ImageView{

	private Bitmap mBitmap;
	private boolean inited;

	// 定义两个常量,这两个常量指定该图片横向,纵向上都被划分为100格
	private final int WIDTH = 100;
	private final int HEIGHT = 100;

	// 记录该图片上包含10201个顶点
	private final int COUNT = (WIDTH + 1) * (HEIGHT + 1);

	// 定义一个数组,记录Bitmap上的101*101个点的坐标
	private final float[] orig = new float[COUNT * 2];

	// 定义一个数组,记录Bitmap上的101*101个点经过扭曲后的坐标
	// 对图片扭曲的关键就是修改该数组里元素的值
	private final float[] verts = new float[COUNT * 2];

	private int bitmapWidth;
	private int bitmapHeight;
	private float boxHeigtht;

	public WaveBottomImageView(Context context) {
		this(context, null);
	}

	public WaveBottomImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mBitmap = ((BitmapDrawable)this.getDrawable()).getBitmap(); 
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 获取图片宽度和高度
		bitmapWidth = getMeasuredWidth(); 
		bitmapHeight = getMeasuredHeight();
		boxHeigtht = bitmapHeight / HEIGHT;
		
		setMeasuredDimension(bitmapWidth, (int)(bitmapHeight + boxHeigtht));
		
		if(!inited){
			init();	
			inited = true;
		}
	}

	protected void onDraw(Canvas canvas) {
		canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, verts, 0, null, 0, null);
	}

	private void init(){
		//初始化
		int index = 0;
		for (int y = 0; y <= HEIGHT; y++) {
			float fy = bitmapHeight * y / HEIGHT;
			for (int x = 0; x <= WIDTH; x++) {
				float fx = bitmapWidth * x / WIDTH;
				// 初始化orig,verts数组
				// 初始化,orig,verts两个数组均匀地保存了101*101个点的x,y坐标 
				orig[index * 2 + 0] = verts[index * 2 + 0] = fx;
				orig[index * 2 + 1] = verts[index * 2 + 1] = fy;
				if(y == HEIGHT){
					// 修改最后一行的y坐标
					float oldY = orig[index * 2 + 1];
					float newY = (float) (oldY + boxHeigtht * Math.sin(Math.PI / 4 * (x % 5)));
					verts[index * 2 + 1] = newY;
				}
				index += 1;
			}
		}
	}
	
//	private void wave() {
//		int index = (WIDTH + 1) * HEIGHT;
//		for (int x = 0; x <= WIDTH; x++) {
//			float oldY = orig[index * 2 + 1];
//			float newY = (float) (oldY + boxHeigtht * Math.sin(Math.PI / 4 * (x % 5)));
//			verts[index * 2 + 1] = newY;
//			index += 1;
//		}
//	}
}


一开始做的时候,没有重写onMeasure,导致波浪效果怎么也出不来,妈蛋的!

转载请标明出处:/article/1908029.html

很可惜这种方式的效率太低了,ListView根本就滑不动啊,于是有了下面这种实现方式!

/**
 * 参考:http://blog.csdn.net/lmj623565791/article/details/42094215
 * */
public class WaveImageView extends ImageView {
	
	private Paint mPaint;
	private Paint mPathPaint;
	private Path mPath;
	private Bitmap mMaskBitmap;
	private static final Xfermode mXfermode = new PorterDuffXfermode(Mode.DST_IN);
	private float mRectFWidth;
	private int mWidth;
	private int mHeight;
	
	public WaveImageView(Context context) {
        this(context, null);
    }

    public WaveImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }
    
    private void init(final Context context, final AttributeSet attrs) {
    	mPaint = new Paint();
    	mPath = new Path();
    	mPathPaint = new Paint();
        mPathPaint.setAntiAlias(true);
        mPathPaint.setColor(0xff000000);
        mPathPaint.setStyle(Paint.Style.FILL);
    }
    
    @Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 获取图片宽度和高度
		mWidth = getMeasuredWidth(); 
		mHeight = getMeasuredHeight();
		mRectFWidth = mWidth / 20.0f; mRectFWidth = mRectFWidth - mRectFWidth%1;//去掉小数部分
	}

    
    @SuppressLint("DrawAllocation")
	@Override
    protected void onDraw(Canvas canvas) {
    	// 拿到Drawable
        Drawable drawable = getDrawable();
        // 获取drawable的宽和高
        int dWidth = drawable.getIntrinsicWidth();
        int dHeight = drawable.getIntrinsicHeight();
        if (drawable != null) {
            // 创建bitmap
            Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
            float scale = 1.0f;
            // 创建画布
            Canvas drawCanvas = new Canvas(bitmap);
            // 按照bitmap的宽高,以及view的宽高,计算缩放比例;因为设置的src宽高比例可能和imageview的宽高比例不同,这里我们不希望图片失真;
            scale = getWidth() * 1.0F / Math.min(dWidth, dHeight);
            // 根据缩放比例,设置bounds,相当于缩放图片了
            drawable.setBounds(0, 0, (int) (scale * dWidth), (int) (scale * dHeight));
            // 1. 先把原图(dst)绘制上
            drawable.draw(drawCanvas);
            // 2. 设置Xfermode
            mPaint.setXfermode(mXfermode);
            // 3. 把mask(src)绘制上
            if (mMaskBitmap == null || mMaskBitmap.isRecycled()) {
                mMaskBitmap = getMaskBitmap();
            }
            drawCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaint);

            // 将准备好的bitmap绘制出来
            canvas.drawBitmap(bitmap, 0, 0, null);
        }
    }
    
    /**
     * 绘制形状
     * 
     * @return
     */
    public Bitmap getMaskBitmap() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        
        RectF oval = new RectF(0, 0, mRectFWidth, mRectFWidth);  
		mPath.addArc(oval, 0, 180);
		mPath.lineTo(0, -(mHeight-mRectFWidth));
		mPath.lineTo(mRectFWidth, -(mHeight-mRectFWidth));
		mPath.lineTo(mRectFWidth, 0);
		
		canvas.translate(0, mHeight-mRectFWidth);
		
		canvas.drawPath(mPath, mPathPaint);
		
		float sum = mRectFWidth;
		while(sum < mWidth){
			canvas.translate(mRectFWidth, 0);
			canvas.drawPath(mPath, mPathPaint);
			sum += mRectFWidth;
		}
		
        return bitmap;
    }
}


竟然也实现了,而且ListView还能滑的动,amazing!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: