在以图片为主的项目数据表界面中,普遍的应用了自定义的ImageView,这增强了图片的表现力。这里以“事件表”介绍一个自定ImageView的实例。这个自定ImageView通过clipPath实现了圆角图片的显示,通过描绘Vector 图标在图片中,绘出了“选择标记”,“星级标记”,“定时任务标记”,“加密标记”及加密类型。
---- 自定的 ImageView
package com.bi3eview.newstart60.local.SelfWidget; import android.graphics.Matrix; import android.support.v7.widget.AppCompatImageView; import android.util.DisplayMetrics; import android.graphics.RectF; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import com.bi3eview.newstart60.local.COMCONST; public class TextImageView extends AppCompatImageView { private static final int TEXT_SIZE = 12;// sp private static int BACKGROUND_COLOR = Color.WHITE; private static int TEXT_COLOR = Color.BLUE; private static int MARKICON_COLOR = Color.YELLOW; private static int SELMARK_COLOR = Color.GREEN; private static int STAR_COLOR = Color.RED; public static String secretName = "se"; public static String topSecretName = "tse"; private int secretLockClass = 0; private int tasknum = 0; private int starClassno = 0; private boolean selmarkblv = false; public TextImageView(Context context, AttributeSet attrs) { super(context, attrs); } public void setSecretClassno(int isecretClass) { secretLockClass = isecretClass; } public void setTimerTasknum(int iTasknum) { tasknum = iTasknum; } public void setStarClassno(int iStarClassno) { starClassno = iStarClassno; } public void setSelectMark(Boolean setselblv) { selmarkblv = setselblv; } @Override public void draw(Canvas canvas) { // 设置图片圆角修剪路经 canvas.save(); Path borderpath = new Path(); int w = this.getWidth(); int h = this.getHeight(); float fCornerRadius = h/6; borderpath.addRoundRect(new RectF(0,0,w,h),fCornerRadius,fCornerRadius,Path.Direction.CW); canvas.clipPath(borderpath); super.draw(canvas); canvas.restore(); // 描绘标记 fCornerRadius = 0; canvas.save(); int iwidth = canvas.getWidth(); int iheight = canvas.getHeight(); final Paint paint = new Paint(); final DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); paint.setColor(MARKICON_COLOR); int ifnsize = (int)(TEXT_SIZE*dm.scaledDensity); paint.setTextSize(ifnsize);// 设置文字大小 int ishapesize = (int)(19*dm.scaledDensity); paint.setStrokeWidth(1); Matrix cmaxtrix = new Matrix(); Path starpath; /** 描绘定时任务标记 */ if(tasknum > 0) { starpath = PathParser.doPath(COMCONST.VECTORPATH_TASK); cmaxtrix.setScale(2, 2); starpath.transform(cmaxtrix); starpath.offset(iwidth - ishapesize - ishapesize / 4, iheight - ishapesize - ishapesize / 4); canvas.drawPath(starpath, paint); } /** 描绘选择标记 */ if(selmarkblv == true) { starpath = PathParser.doPath(COMCONST.VECTORPATH_SELMARK); cmaxtrix.reset(); cmaxtrix.setScale(4, 4); starpath.transform(cmaxtrix); starpath.offset(iwidth/2 - ishapesize, iheight/2 - ishapesize/2); paint.setColor(SELMARK_COLOR); canvas.drawPath(starpath, paint); } /** 描绘星级标记 */ if(starClassno >= 10){ int istarjn = starClassno/10; starpath = PathParser.doPath(COMCONST.VECTORPATH_STAR); cmaxtrix.reset(); cmaxtrix.setScale((float)1.5, (float)1.5); starpath.transform(cmaxtrix); starpath.offset(ishapesize/6, ishapesize/3); paint.setColor(STAR_COLOR); canvas.drawPath(starpath, paint); if(istarjn > 1) { for(int j = 1;j < istarjn;j++) { starpath.offset(ishapesize, 0); canvas.drawPath(starpath, paint); } } } /** 描绘“加密标记”及标注加密类型 */ if(secretLockClass > 0) { paint.setColor(MARKICON_COLOR); starpath = PathParser.doPath(COMCONST.VECTORPATH_LOCK); cmaxtrix.reset(); cmaxtrix.setScale(2, 2); starpath.transform(cmaxtrix); starpath.offset(ishapesize / 4, iheight - ishapesize-ishapesize/5);// (100,100); canvas.drawPath(starpath, paint); String secretTxt = secretName;//" 秘密 "; if(secretLockClass == 2) secretTxt = topSecretName;//" 绝密 "; int iclen = secretTxt.length(); // 设置Rect Path Path path = new Path(); int iLeft = ishapesize / 3+ishapesize; if(iclen > 2) iclen = iclen-1; int iRight = iLeft+ifnsize*iclen+ifnsize / 3; path.addRect(iLeft, iheight-ifnsize-ifnsize/2, iRight, iheight-ifnsize/3, Path.Direction.CW); path.setFillType(Path.FillType.WINDING); paint.setColor(BACKGROUND_COLOR); canvas.drawPath(path, paint); paint.setColor(TEXT_COLOR); canvas.drawText(secretTxt,ishapesize / 2+ishapesize,iheight-ifnsize/2,paint); } canvas.restore(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } }
----- 自定ImageView中用到 vector path Parser 的相关代码及数据
package com.bi3eview.newstart60.local.SelfWidget; import android.graphics.Path; import android.graphics.RectF; import android.util.Log; public class PathParser { private static final String TAG = "SvgToPath.TAG"; /* * This is where the hard-to-parse paths are handled. * Uppercase rules are absolute positions, lowercase are relative. * Types of path rules: * <p/> * <ol> * <li>M/m - (x y)+ - Move to (without drawing) * <li>Z/z - (no params) - Close path (back to starting point) * <li>L/l - (x y)+ - Line to * <li>H/h - x+ - Horizontal ine to * <li>V/v - y+ - Vertical line to * <li>C/c - (x1 y1 x2 y2 x y)+ - Cubic bezier to * <li>S/s - (x2 y2 x y)+ - Smooth cubic bezier to (shorthand that assumes the x2, y2 from previous C/S is the x1, y1 of this bezier) * <li>Q/q - (x1 y1 x y)+ - Quadratic bezier to * <li>T/t - (x y)+ - Smooth quadratic bezier to (assumes previous control point is "reflection" of last one w.r.t. to current point) * </ol> * <p/> * Numbers are separate by whitespace, comma or nothing at all (!) if they are self-delimiting, (ie. begin with a - sign) */ public static Path doPath(String s) { int n = s.length(); ParserHelper ph = new ParserHelper(s); ph.skipWhitespace(); Path p = new Path(); float lastX = 0; float lastY = 0; float lastX1 = 0; float lastY1 = 0; float contourInitialX = 0; float contourInitialY = 0; RectF r = new RectF(); char cmd = 'x'; while (ph.pos < n) { char next = s.charAt(ph.pos); if (!Character.isDigit(next) && !(next == '.') && !(next == '-')) { cmd = next; ph.advance(); } else if (cmd == 'M') { // implied command cmd = 'L'; } else if (cmd == 'm') { // implied command cmd = 'l'; } else { // implied command //ignore } p.computeBounds(r, true); // Log.d(TAG, " " + cmd + " " + r); // Util.debug("* Commands remaining: '" + path + "'."); boolean wasCurve = false; switch (cmd) { case 'M': case 'm': { float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 'm') { p.rMoveTo(x, y); lastX += x; lastY += y; } else { p.moveTo(x, y); lastX = x; lastY = y; } contourInitialX = lastX; contourInitialY = lastY; break; } case 'Z': case 'z': { /// p.lineTo(contourInitialX, contourInitialY); p.close(); lastX = contourInitialX; lastY = contourInitialY; break; } case 'L': case 'l': { float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 'l') { p.rLineTo(x, y); lastX += x; lastY += y; } else { p.lineTo(x, y); lastX = x; lastY = y; } break; } case 'H': case 'h': { float x = ph.nextFloat(); if (cmd == 'h') { p.rLineTo(x, 0); lastX += x; } else { p.lineTo(x, lastY); lastX = x; } break; } case 'V': case 'v': { float y = ph.nextFloat(); if (cmd == 'v') { p.rLineTo(0, y); lastY += y; } else { p.lineTo(lastX, y); lastY = y; } break; } case 'C': case 'c': { wasCurve = true; float x1 = ph.nextFloat(); float y1 = ph.nextFloat(); float x2 = ph.nextFloat(); float y2 = ph.nextFloat(); float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 'c') { x1 += lastX; x2 += lastX; x += lastX; y1 += lastY; y2 += lastY; y += lastY; } p.cubicTo(x1, y1, x2, y2, x, y); lastX1 = x2; lastY1 = y2; lastX = x; lastY = y; break; } case 'S': case 's': { wasCurve = true; float x2 = ph.nextFloat(); float y2 = ph.nextFloat(); float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 's') { x2 += lastX; x += lastX; y2 += lastY; y += lastY; } float x1 = 2 * lastX - lastX1; float y1 = 2 * lastY - lastY1; p.cubicTo(x1, y1, x2, y2, x, y); lastX1 = x2; lastY1 = y2; lastX = x; lastY = y; break; } case 'A': case 'a': { float rx = ph.nextFloat(); float ry = ph.nextFloat(); float theta = ph.nextFloat(); int largeArc = (int) ph.nextFloat(); int sweepArc = (int) ph.nextFloat(); float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 'a') { x += lastX; y += lastY; } drawArc(p, lastX, lastY, x, y, rx, ry, theta, largeArc == 1, sweepArc == 1); lastX = x; lastY = y; break; } case 'T': case 't': { wasCurve = true; float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 't') { x += lastX; y += lastY; } float x1 = 2 * lastX - lastX1; float y1 = 2 * lastY - lastY1; p.cubicTo( lastX, lastY, x1, y1, x, y ); lastX = x; lastY = y; lastX1 = x1; lastY1 = y1; break; } case 'Q': case 'q': { wasCurve = true; float x1 = ph.nextFloat(); float y1 = ph.nextFloat(); float x = ph.nextFloat(); float y = ph.nextFloat(); if (cmd == 'q') { x += lastX; y += lastY; x1 += lastX; y1 += lastY; } p.cubicTo( lastX, lastY, x1, y1, x, y ); lastX1 = x1; lastY1 = y1; lastX = x; lastY = y; break; } default: Log.w(TAG, "Invalid path command: " + cmd); ph.advance(); } if (!wasCurve) { lastX1 = lastX; lastY1 = lastY; } ph.skipWhitespace(); } return p; } /* * Elliptical arc implementation based on the SVG specification notes * Adapted from the Batik library (Apache-2 license) by SAU */ private static void drawArc(Path path, double x0, double y0, double x, double y, double rx, double ry, double angle, boolean largeArcFlag, boolean sweepFlag) { double dx2 = (x0 - x) / 2.0; double dy2 = (y0 - y) / 2.0; angle = Math.toRadians(angle % 360.0); double cosAngle = Math.cos(angle); double sinAngle = Math.sin(angle); double x1 = (cosAngle * dx2 + sinAngle * dy2); double y1 = (-sinAngle * dx2 + cosAngle * dy2); rx = Math.abs(rx); ry = Math.abs(ry); double Prx = rx * rx; double Pry = ry * ry; double Px1 = x1 * x1; double Py1 = y1 * y1; // check that radii are large enough double radiiCheck = Px1 / Prx + Py1 / Pry; if (radiiCheck > 1) { rx = Math.sqrt(radiiCheck) * rx; ry = Math.sqrt(radiiCheck) * ry; Prx = rx * rx; Pry = ry * ry; } // Step 2 : Compute (cx1, cy1) double sign = (largeArcFlag == sweepFlag) ? -1 : 1; double sq = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1)); sq = (sq < 0) ? 0 : sq; double coef = (sign * Math.sqrt(sq)); double cx1 = coef * ((rx * y1) / ry); double cy1 = coef * -((ry * x1) / rx); double sx2 = (x0 + x) / 2.0; double sy2 = (y0 + y) / 2.0; double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1); double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1); // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle) double ux = (x1 - cx1) / rx; double uy = (y1 - cy1) / ry; double vx = (-x1 - cx1) / rx; double vy = (-y1 - cy1) / ry; double p, n; // Compute the angle start n = Math.sqrt((ux * ux) + (uy * uy)); p = ux; // (1 * ux) + (0 * uy) sign = (uy < 0) ? -1.0 : 1.0; double angleStart = Math.toDegrees(sign * Math.acos(p / n)); // Compute the angle extent n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); p = ux * vx + uy * vy; sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; double angleExtent = Math.toDegrees(sign * Math.acos(p / n)); if (!sweepFlag && angleExtent > 0) { angleExtent -= 360f; } else if (sweepFlag && angleExtent < 0) { angleExtent += 360f; } angleExtent %= 360f; angleStart %= 360f; RectF oval = new RectF((float) (cx - rx), (float) (cy - ry), (float) (cx + rx), (float) (cy + ry)); path.addArc(oval, (float) angleStart, (float) angleExtent); } }
------ vector path 数据表
package com.bi3eview.newstart60.local; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Color; import android.os.Build; import android.database.Cursor; import android.os.Environment; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.view.Gravity; import android.view.View; import android.widget.EditText; import android.text.InputFilter; import android.widget.Toast; import android.widget.ImageView; import android.widget.TextView; import android.widget.LinearLayout; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; public class COMCONST { // 。。。。。。 // vector path public static final String VECTORPATH_TASK = "M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"; public static final String VECTORPATH_STAR = "M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"; public static final String VECTORPATH_SELMARK = "M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"; public static final String VECTORPATH_LOCK = "M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z";; // 。。。。 }
标签:--,double,APP,float,int,import,ImageView,android,ph From: https://www.cnblogs.com/newstart60/p/16970745.html