先看看图片的效果,左边是原图,右边是旋转之后的图;
之所以把这个写出来是因为在一个项目中需要用到这样的效果,我试过用FrameLayout布局如上的画面,然后旋转FrameLayout,随之而来也就存在了一些问题——锯齿!
在网上搜索之后,有两种方法,一是利用Paint,二是利用Canvas;
(1)、paint.setAntiAlias(true);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
(2)、DrawFilter pfdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
canvas.setDrawFilter(pfdf);
而如果利用paint,或者canvas,需要从哪获取paint/canvas,这也是一个问题;
在实现的过程中,尝试过自定义FrameLayout下面的单个View{ImageView,TextView},但都以失败告终,失败的主要问题在于右图下边的文字描述无法和相片边框相对齐,而且用Matrix旋转背景之后背景大小改变,位置也不在最下边,所以就采用了单独实现一个View的方法,主要原因还是因为自身对Canvas绘图及Paint画笔不是很熟悉,所以导致的效率不高;
public class RotateTextImageView extendsView {
PaintFlagsDrawFilter pfdf;
Paint paint;
Matrix matrix;
Bitmap bitmap;int index = -1;private intoriHeight;private intoriWidth;private intnewHeight;private intnewWidth;private int angle = 5;protected Path path = newPath();private float[] f = new float[8];private int shawHeight = 20;private int borderSize = 8;
Bitmap oriBitmap;private String text = "";public RotateTextImageView(Context context, AttributeSet attrs, intdefStyle) {super(context, attrs, defStyle);
initCanvasInfo();
}publicRotateTextImageView(Context context, AttributeSet attrs) {super(context, attrs);
initCanvasInfo();
}publicRotateTextImageView(Context context) {super(context);
initCanvasInfo();
}/*** 初始化Paint*/
protected voidinitCanvasInfo() {
pfdf= new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
paint= newPaint();
paint.setAntiAlias(true);
matrix= newMatrix();
matrix.setRotate(5);
}
@Overrideprotected voidonDraw(Canvas canvas) {super.onDraw(canvas);
paint.reset();//消除锯齿
paint.setAntiAlias(true);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
canvas.setDrawFilter(pfdf);
canvas.drawBitmap(bitmap,0, 0, paint);
newHeight=bitmap.getHeight();
newWidth=bitmap.getWidth();
calculatePoints();//添加阴影
path.reset();
path.moveTo(f[0], f[1]);
path.lineTo(f[2], f[3]);
path.lineTo(f[4], f[5]);
path.lineTo(f[6], f[7]);
path.close();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.parseColor("#96ffffff"));
canvas.drawPath(path, paint);//添加字符
if (text != null && !text.equals("")) {
path.reset();
paint.setTextSize(18);float width =paint.measureText(text);
path.moveTo((f[0] + f[2]) / 2, (f[1] + f[3]) / 2);
path.lineTo((f[4] + f[6]) / 2, (f[5] + f[7]) / 2);
paint.setColor(Color.parseColor("#2b2b2b"));
canvas.drawTextOnPath(text, path, (oriWidth- width) / 2, 3, paint);
}
layout(0, 0, newWidth, newHeight);
}/*** 计算坐标值*/
private voidcalculatePoints() {double a = angle * Math.PI / 180;
BigDecimal height= newBigDecimal(oriHeight);
BigDecimal width= newBigDecimal(oriWidth);
BigDecimal cos= newBigDecimal(Math.cos(a));
BigDecimal tan= newBigDecimal(Math.tan(a));
f[0] = 0;
f[1] =height.multiply(cos).floatValue();
f[2] = tan.multiply(newBigDecimal(shawHeight)).floatValue();
f[3] = (new BigDecimal(f[1])).subtract(newBigDecimal(shawHeight))
.floatValue();
f[4] = width.multiply(cos).add(new BigDecimal(f[2])).floatValue();
f[5] = new BigDecimal(newHeight -shawHeight).floatValue();
f[6] =width.multiply(cos).floatValue();
f[7] = newBigDecimal(newHeight).floatValue();
}/*** 设置图片
*
*@parambmp*/
public voidsetBitmap(Bitmap bmp) {
oriBitmap=bmp;
matrix.reset();
matrix.setRotate(angle);
Bitmap bitmapF=addFrame(bmp);
oriHeight=bitmapF.getHeight();
oriWidth=bitmapF.getWidth();
bitmap= Bitmap.createBitmap(bitmapF, 0, 0, bitmapF.getWidth(),
bitmapF.getHeight(), matrix,true);
postInvalidate();
}/*** 旋转角度
*
*@paramangle*/
public void setAngle(intangle) {this.angle =angle;
setBitmap(oriBitmap);
}/*** 设置底部阴影高度
*
*@paramshawHeight*/
public void setShawHeight(intshawHeight) {this.shawHeight =shawHeight;
postInvalidate();
}/*** 生成添加了白色边缘的图
*
*@parambmp
*@return
*/
protectedBitmap addFrame(Bitmap bmp) {
Bitmap bmpWithBorder= Bitmap.createBitmap(bmp.getWidth() +borderSize* 2, bmp.getHeight() + borderSize * 2, bmp.getConfig());
Canvas canvas= newCanvas(bmpWithBorder);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bmp, borderSize, borderSize,null);returnbmpWithBorder;
}/*** 设置字符串
*
*@paramtext*/
public voidsetText(String text) {this.text =text;
postInvalidate();
}/*** 获取字体高度*/
protected intgetFontHeight() {
FontMetrics fm=paint.getFontMetrics();return (int) Math.ceil(fm.descent - fm.top) + 2;
}
}
代码解释:其实没有什么难的东西,只是一些数学运算,代码中每一个方法都有对应的功能注释。浮点型数组代表阴影层四个坐标点的八个坐标值,分别是左下、左上、右上、右下四个点,阴影层坐标计算也比较简单,但有点繁琐,就是把原图旋转之后再根据几何知识进行求解坐标!
每次重新设置角度,设置图片,都需要重新绘制图形-->postInvalidate();
View的使用
一、xml配置文件
android:id="@+id/myview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:minHeight="250dip"android:minWidth="200dip"android:paddingLeft="5dip" />
二、设置文字说明及角度、图片
RotateTextImageView myView =(RotateTextImageView) findViewById(R.id.myview);
myView.setShawHeight(50);
Bitmap bmp=BitmapFactory.decodeResource(getResources(),R.drawable.test1);
myView.setBitmap(bmp);
myView.setAngle(10);
myView.setText("这是一个测试");