仿半塘图片添加标签功能
2016-02-02 11:51
232 查看
模仿半塘app的图片添加标签功能,刚开始反编译了半塘的代码,结果代码太多了,用一些三方的东西,觉的比较麻烦,这里自己写了一下实现,感觉和半塘的没啥区别(自我感觉良好,嘿嘿)
一、半塘功能实现步骤
二、半塘实现分析
功能分析
- 本地相册选择
- 添加图片
- 添加标签
- 标签移动
- 标签动画切换
- 图片生成
实现说明
(1) 标签类型有两种 第一种是单个标签 第二种是两个标签
(2) 第一种标签的包含:原点和文字
(3) 第二步标签包含:原点、文字和横线
(4) 原点的位置是点击的位置
(5) 文字有两种样式,一种是向左的,一种是向右的(对应实现)
(6) 横线有四种样式
三、实现
(1)类结构图
(2)代码结构
(3)具体实现
圆点的实现
文字的实现
初始化
画第一种类型
画第二种类型
线条的实现
初始化
四种类型
LabelViewListener标签的实现监听
包含:标签的位置、切换样式、显示和隐藏动画、更新坐标(中心)、更新内容、判断是否点击到中心等方法。
只有一个内容的标签
有两种绘制模式,包含原点和文字,记录中心位置和当前的模式
包含绘制两种模式的方法、显示和隐藏的动画、提供view的大小和位置等。
第一种模式
第二种模式
显示动画
隐藏动画
有两个内容的标签
包含圆点、线条和文字
有四种绘制模式
第一种模式
第二种模式
第二种模式
第四种模式
以上大致说了一下思路
这是代码链接
https://github.com/gyh/GCustomView
一、半塘功能实现步骤
二、半塘实现分析
功能分析
- 本地相册选择
- 添加图片
- 添加标签
- 标签移动
- 标签动画切换
- 图片生成
实现说明
(1) 标签类型有两种 第一种是单个标签 第二种是两个标签
(2) 第一种标签的包含:原点和文字
(3) 第二步标签包含:原点、文字和横线
(4) 原点的位置是点击的位置
(5) 文字有两种样式,一种是向左的,一种是向右的(对应实现)
(6) 横线有四种样式
三、实现
(1)类结构图
(2)代码结构
(3)具体实现
圆点的实现
public class LabelRoundDot extends Drawable{ private Paint mPaint; private Bitmap mBitmap; private RectF rectF; public LabelRoundDot(Bitmap bitmap) { mBitmap = bitmap; BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setShader(bitmapShader); } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); rectF = new RectF(left, top, right, bottom); } @Override public void draw(Canvas canvas) { canvas.drawRoundRect(rectF, 30, 30, mPaint); } @Override public int getIntrinsicWidth() { return mBitmap.getWidth(); } @Override public int getIntrinsicHeight() { return mBitmap.getHeight(); } @Override public void setAlpha(int alpha) { mPaint.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { mPaint.setColorFilter(cf); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } }
文字的实现
初始化
public LabelTextView(String labelText, int textType){ this.labelText = labelText; this.currentType = textType; mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setTextSize(TEXT_SIZE); initLabel(); } private void initLabel(){ Rect mBounds = new Rect(); mPaint.getTextBounds(this.labelText, 0, this.labelText.length(), mBounds); this.labelTextHeight = mBounds.height() + VIEW_PADDING; this.labelTextWidth = labelTextHeight/2 +(mBounds.width()<6? 6:mBounds.width()) + VIEW_PADDING; Log.i(TAG, "initLabel labelTextHeight = " + labelTextHeight + " labelTextWidth = " + labelTextWidth); }
画第一种类型
private void drawFrist(Canvas canvas){ mPaint.setStrokeWidth(3); mPaint.setColor(Color.parseColor("#99000000")); //画半圆 RectF oval = new RectF(0, 0, labelTextHeight, labelTextHeight); canvas.drawArc(oval, 270, -180, true, mPaint); Rect targetRect = new Rect(labelTextHeight/2, 0, labelTextWidth - VIEW_PADDING, labelTextHeight); canvas.drawRect(targetRect, mPaint); //画三角形 Path path = new Path(); path.moveTo(labelTextWidth - VIEW_PADDING, 0);// 此点为多边形的起点 path.lineTo(labelTextWidth, labelTextHeight/2); path.lineTo(labelTextWidth - VIEW_PADDING, labelTextHe 4000 ight); path.close(); // 使这些点构成封闭的多边形 canvas.drawPath(path, mPaint); //写文字 mPaint.setColor(Color.parseColor("#ffffff")); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2; // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX() mPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(labelText, targetRect.centerX(), baseline, mPaint); }
画第二种类型
private void drawSecond(Canvas canvas){ Log.i(TAG, "onDrawSecond ---------"); mPaint.setStrokeWidth(3); mPaint.setColor(Color.parseColor("#99000000")); //画半圆 RectF oval = new RectF(labelTextWidth - labelTextHeight, 0, labelTextWidth, labelTextHeight); canvas.drawArc(oval,90, -180, true, mPaint); //画矩形 Rect targetRect = new Rect(VIEW_PADDING, 0, labelTextWidth-labelTextHeight/2, labelTextHeight); canvas.drawRect(targetRect, mPaint); //画三角形 Path path = new Path(); path.moveTo(VIEW_PADDING, 0);// 此点为多边形的起点 path.lineTo(0, labelTextHeight/2); path.lineTo(VIEW_PADDING, labelTextHeight); path.close(); // 使这些点构成封闭的多边形 canvas.drawPath(path, mPaint); //写文字 mPaint.setColor(Color.parseColor("#ffffff")); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2; // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX() mPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(labelText, targetRect.centerX(), baseline, mPaint); }
线条的实现
初始化
public LabelLineView (int type){ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStrokeWidth(3); mPaint.setColor(Color.parseColor("#99000000")); labelHeight = slashHeight; labelWidth = slashWidth + straightLine; this.currentType = type; Log.i(TAG, "onDrawFirst labelHeight = " + labelHeight + " labelWidth = " + labelWidth); }
四种类型
/** * * @param canvas */ private void drawFrist(Canvas canvas){ //画第一条直线 int lineSx = 0; int lineSy = 0; int lineEx = straightLine; int lineEy = 0; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 lineSx = straightLine; lineSy = 0; lineEx = labelWidth; lineEy = labelHeight; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 } /** * * @param canvas */ private void drawSecond(Canvas canvas){ //画第一条直线 int lineSx = 0; int lineSy = labelHeight; int lineEx = straightLine; int lineEy = labelHeight; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 lineSx = straightLine; lineSy = labelHeight; lineEx = labelWidth; lineEy = 0; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 } private void drawThird(Canvas canvas){ int lineSx = 0; int lineSy = labelHeight; int lineEx = slashWidth; int lineEy = 0; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 lineSx = slashWidth; lineSy = 0; lineEx = labelWidth; lineEy = 0; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 } private void drawFourth(Canvas canvas){ //画第一条直线 int lineSx = 0; int lineSy = 0; int lineEx = slashWidth; int lineEy = slashHeight; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 lineSx = slashWidth; lineSy = slashHeight; lineEx = labelWidth; lineEy = labelHeight; canvas.drawLine(lineSx, lineSy, lineEx, lineEy, mPaint);// 画线 }
LabelViewListener标签的实现监听
包含:标签的位置、切换样式、显示和隐藏动画、更新坐标(中心)、更新内容、判断是否点击到中心等方法。
只有一个内容的标签
有两种绘制模式,包含原点和文字,记录中心位置和当前的模式
包含绘制两种模式的方法、显示和隐藏的动画、提供view的大小和位置等。
第一种模式
/** * 绘制第一模式 * * @param canvas */ private void onDrawFirst(Canvas canvas) { Log.i(TAG, "onDrawFirst ---------"); canvas.drawBitmap(Utils.drawableToBitmap(labelTextView),4,0,mPaint); //画原点 int xBmp = labelViewWidth-originPic.getWidth(); int yBmp = (labelViewHeight-originPic.getWidth())/2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp); }
第二种模式
/** * 绘制第二模式 * * @param canvas */ private void onDrawSecond(Canvas canvas) { Log.i(TAG, "onDrawSecond ---------"); canvas.drawBitmap(Utils.drawableToBitmap(labelTextView), originPic.getWidth()-4, 0, mPaint); //画原点 int xBmp = 0; int yBmp = (labelViewHeight-originPic.getWidth())/2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp); }
显示动画
@Override public ValueAnimator getLabelShowAnim() { ValueAnimator anim = null; if (currentType == FRIST_MODEL) { anim = ValueAnimator.ofInt(labelViewWidth, 0); } else if (currentType == SECOND_MODEL) { anim = ValueAnimator.ofInt(0, labelViewWidth); } if (anim == null) { return null; } anim.setDuration(500); return anim; }
隐藏动画
@Override public ValueAnimator getLabelHideAnim() { ValueAnimator anim = null; if (currentType == FRIST_MODEL) { anim = ValueAnimator.ofInt(0, labelViewWidth); } else if (currentType == SECOND_MODEL) { anim = ValueAnimator.ofInt(labelViewWidth, 0); } if (anim == null) { return null; } anim.setDuration(500); return anim; }
有两个内容的标签
包含圆点、线条和文字
有四种绘制模式
第一种模式
/** * 绘制第一模式 * * @param canvas */ private void onDrawFirst(Canvas canvas) { Log.i(TAG, "onDrawFirst ---------"); //上面的文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst), labelViewWidth-originPic.getWidth()-labelLineViewFirst.getIntrinsicWidth()-labelTextViewFirst.getIntrinsicWidth(), 0,mPaint); //上面的线条 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst), labelViewWidth-originPic.getWidth()-labelLineViewFirst.getIntrinsicWidth(), labelTextViewFirst.getIntrinsicHeight()/2, mPaint); //下面的文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond), labelViewWidth - originPic.getWidth() - labelLineViewSecond.getIntrinsicWidth() - labelTextViewSecond.getIntrinsicWidth(), labelViewHeight - labelTextViewSecond.getIntrinsicHeight(), mPaint); //下面的线条 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond), labelViewWidth - originPic.getWidth() - labelLineViewSecond.getIntrinsicWidth(), labelTextViewFirst.getIntrinsicHeight() / 2 + labelLineViewFirst.getIntrinsicHeight(), mPaint); //画原点 int xBmp = labelViewWidth - originPic.getWidth(); int yBmp = (labelViewHeight - originPic.getWidth()) / 2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawFirst xBmp = " + xBmp + " yBmp = " + yBmp); }
第二种模式
/** * 绘制第二模式 * * @param canvas */ private void onDrawSecond(Canvas canvas) { Log.i(TAG, "onDrawSecond ---------"); //上面条线 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst), originPic.getWidth(), labelTextViewFirst.getIntrinsicHeight()/2, mPaint); //上面文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst), originPic.getWidth()+labelLineViewFirst.getIntrinsicWidth(), 0, mPaint); //下面线条 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond), originPic.getWidth(), labelTextViewFirst.getIntrinsicHeight()/2+labelLineViewFirst.getIntrinsicHeight(), mPaint); //下面文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond), originPic.getWidth()+labelLineViewSecond.getIntrinsicWidth(), labelViewHeight - labelTextViewSecond.getIntrinsicHeight(), mPaint); //画原点 int xBmp = 0; int yBmp = (labelViewHeight-originPic.getWidth())/2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp); }
第二种模式
/** * 第三种绘制 */ private void onDrawThird(Canvas canvas){ Log.i(TAG, "onDrawSecond ---------"); //左边的文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst), 0, 0, mPaint); //上面条线 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst), labelTextViewFirst.getIntrinsicWidth(), labelTextViewFirst.getIntrinsicHeight()/2, mPaint); //画原点 int xBmp = labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth(); int yBmp = (labelViewHeight-originPic.getHeight())/2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp); //下面线条 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond), labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth()+originPic.getWidth(), labelViewHeight/2, mPaint); //下面文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond), labelViewWidth - labelTextViewSecond.getIntrinsicWidth(), labelViewHeight - labelTextViewSecond.getIntrinsicHeight(), mPaint); }
第四种模式
/** * 第四种绘制 */ private void onDrawFourth(Canvas canvas){ Log.i(TAG, "onDrawFourth ---------"); //左边文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewFirst), 0, labelViewHeight-labelTextViewFirst.getIntrinsicHeight(), mPaint); //左边条线 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewFirst), labelTextViewFirst.getIntrinsicWidth(), labelViewHeight-labelTextViewFirst.getIntrinsicHeight()/2-labelLineViewFirst.getIntrinsicHeight(), mPaint); //画原点 int xBmp = labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth(); int yBmp = (labelViewHeight-originPic.getWidth())/2; canvas.drawBitmap(originPic, xBmp, yBmp, null); Log.i(TAG, "onDrawSecond xBmp = " + xBmp + " yBmp = " + yBmp); //右边线条 canvas.drawBitmap(Utils.drawableToBitmap(labelLineViewSecond), labelTextViewFirst.getIntrinsicWidth()+labelLineViewFirst.getIntrinsicWidth()+originPic.getWidth(), labelTextViewSecond.getIntrinsicHeight()/2, mPaint); //右边文字 canvas.drawBitmap(Utils.drawableToBitmap(labelTextViewSecond), labelViewWidth-labelTextViewSecond.getIntrinsicWidth(), 0, mPaint); }
以上大致说了一下思路
这是代码链接
https://github.com/gyh/GCustomView
相关文章推荐
- Gifski:一个跨平台的高质量 GIF 编码器
- 按右键另存图片只能存BMP
- photoshop去除图片上的水印
- 表格标签table深入了解
- WEB标准网页布局中尽量不要使用的HTML标签
- 模仿动画的放大缩小容器
- 如何使用jquery easyui创建标签组件
- upload上传单张图片
- 图片引发的溢出危机(图)
- C#实现把彩色图片灰度化代码分享
- C#将图片和字节流互相转换并显示到页面上
- C#监控文件夹并自动给图片文件打水印的方法
- web标准知识――用途相似的标签
- 纯CSS实现的当鼠标移上图片添加阴影效果代码
- C#实现打开画图的同时载入图片、最大化显示画图窗体的方法
- 随鼠标移动的图片或文字特效代码
- CSS 图片横向排列实现代码
- C#实现将Email地址转成图片显示的方法
- jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween
- 超级经典一套鼠标控制左右滚动图片带自动翻滚