Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明
先看看圖片的效果,左邊是原圖,右邊是旋轉(zhuǎn)之后的圖;
?
之所以把這個(gè)寫出來是因?yàn)樵谝粋€(gè)項(xiàng)目中需要用到這樣的效果,我試過用FrameLayout布局如上的畫面,然后旋轉(zhuǎn)FrameLayout,隨之而來也就存在了一些問題——鋸齒!
在網(wǎng)上搜索之后,有兩種方法,一是利用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,這也是一個(gè)問題;
在實(shí)現(xiàn)的過程中,嘗試過自定義FrameLayout下面的單個(gè)View{ImageView,TextView},但都以失敗告終,失敗的主要問題在于右圖下邊的文字描述無法和相片邊框相對(duì)齊,而且用Matrix旋轉(zhuǎn)背景之后背景大小改變,位置也不在最下邊,所以就采用了單獨(dú)實(shí)現(xiàn)一個(gè)View的方法,主要原因還是因?yàn)樽陨韺?duì)Canvas繪圖及Paint畫筆不是很熟悉,所以導(dǎo)致的效率不高;
public class RotateTextImageView extends View {PaintFlagsDrawFilter pfdf;Paint paint;Matrix matrix;Bitmap bitmap;int index = -1;private int oriHeight;private int oriWidth;private int newHeight;private int newWidth;private int angle = 5;protected Path path = new Path();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, int defStyle) {super(context, attrs, defStyle);initCanvasInfo();}public RotateTextImageView(Context context, AttributeSet attrs) {super(context, attrs);initCanvasInfo();}public RotateTextImageView(Context context) {super(context);initCanvasInfo();}/*** 初始化Paint*/protected void initCanvasInfo() {pfdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG);paint = new Paint();paint.setAntiAlias(true);matrix = new Matrix();matrix.setRotate(5);}@Overrideprotected void onDraw(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);}/*** 計(jì)算坐標(biāo)值*/private void calculatePoints() {double a = angle * Math.PI / 180;BigDecimal height = new BigDecimal(oriHeight);BigDecimal width = new BigDecimal(oriWidth);BigDecimal cos = new BigDecimal(Math.cos(a));BigDecimal tan = new BigDecimal(Math.tan(a));f[0] = 0;f[1] = height.multiply(cos).floatValue();f[2] = tan.multiply(new BigDecimal(shawHeight)).floatValue();f[3] = (new BigDecimal(f[1])).subtract(new BigDecimal(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] = new BigDecimal(newHeight).floatValue();}/*** 設(shè)置圖片* * @param bmp*/public void setBitmap(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();}/*** 旋轉(zhuǎn)角度* * @param angle*/public void setAngle(int angle) {this.angle = angle;setBitmap(oriBitmap);}/*** 設(shè)置底部陰影高度* * @param shawHeight*/public void setShawHeight(int shawHeight) {this.shawHeight = shawHeight;postInvalidate();}/*** 生成添加了白色邊緣的圖* * @param bmp* @return*/protected Bitmap addFrame(Bitmap bmp) {Bitmap bmpWithBorder = Bitmap.createBitmap(bmp.getWidth() + borderSize* 2, bmp.getHeight() + borderSize * 2, bmp.getConfig());Canvas canvas = new Canvas(bmpWithBorder);canvas.drawColor(Color.WHITE);canvas.drawBitmap(bmp, borderSize, borderSize, null);return bmpWithBorder;}/*** 設(shè)置字符串* * @param text*/public void setText(String text) {this.text = text;postInvalidate();}/*** 獲取字體高度*/protected int getFontHeight() {FontMetrics fm = paint.getFontMetrics();return (int) Math.ceil(fm.descent - fm.top) + 2;} }?
代碼解釋:其實(shí)沒有什么難的東西,只是一些數(shù)學(xué)運(yùn)算,代碼中每一個(gè)方法都有對(duì)應(yīng)的功能注釋。浮點(diǎn)型數(shù)組代表陰影層四個(gè)坐標(biāo)點(diǎn)的八個(gè)坐標(biāo)值,分別是左下、左上、右上、右下四個(gè)點(diǎn),陰影層坐標(biāo)計(jì)算也比較簡(jiǎn)單,但有點(diǎn)繁瑣,就是把原圖旋轉(zhuǎn)之后再根據(jù)幾何知識(shí)進(jìn)行求解坐標(biāo)!
每次重新設(shè)置角度,設(shè)置圖片,都需要重新繪制圖形-->postInvalidate();
View的使用
一、xml配置文件
<com.livingstone.RotateTextImageViewandroid:id="@+id/myview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:minHeight="250dip"android:minWidth="200dip"android:paddingLeft="5dip" />二、設(shè)置文字說明及角度、圖片
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("這是一個(gè)測(cè)試");?
Ex:獲取字體寬度的兩種方法
<1>.通過paint獲取字體的Rect
<2>.通過paint直接獲取字體寬度
intwidth=(int)paint.measureText("你好",0,1); Log.v("width:","width:"+width);?
?
轉(zhuǎn)載于:https://www.cnblogs.com/a284628487/p/3377925.html
總結(jié)
以上是生活随笔為你收集整理的Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 拳皇02出招表是什么(拳皇系列下载)
 - 下一篇: php中count是什么意思?