自定义初学5——自定义View显示图片

清疚 2021-09-22 04:56 680阅读 0赞

前面已经简单介绍过一些自定义View的实现,现在再利用自定义View实现显示一张图片的功能

1、首先编写attrs.xml文件





























2、在自定义View中获得我们自定义属性:

public class CustomImageView extends View {

  1. /\*\*
  2. \* 自定义View的宽
  3. \*/
  4. private int mWidth;
  5. /\*\*
  6. \* 自定义View的高
  7. \*/
  8. private int mHeight;
  9. /\*\*
  10. \* 自定义View的图片
  11. \*/
  12. private Bitmap mImage;
  13. /\*\*
  14. \* 图片的缩放模式
  15. \*/
  16. private int mImageScale;
  17. private static final int IMAGE\_SCALE\_FITXY = 0;
  18. private static final int IMAGE\_SCALE\_CENTER = 1;
  19. /\*\*
  20. \* 图片的标题
  21. \*/
  22. private String mTitle;
  23. /\*\*
  24. \* 字体的颜色
  25. \*/
  26. private int mTextColor;
  27. /\*\*
  28. \* 字体的大小
  29. \*/
  30. private int mTextSize;
  31. private Paint mPaint;
  32. /\*\*
  33. \* 文本的绘制范围
  34. \*/
  35. private Rect mTextBound;
  36. /\*\*
  37. \* 需要绘制的整个矩形范围
  38. \*/
  39. private Rect rect;
  40. public CustomImageView(Context context) \{
  41. this(context, null);
  42. \}
  43. public CustomImageView(Context context, AttributeSet attrs) \{
  44. this(context, attrs, 0);
  45. \}
  46. /\*\*
  47. \* 初始化自定义类型
  48. \*
  49. \* @param context
  50. \* @param attrs
  51. \* @param defStyle
  52. \*/
  53. public CustomImageView(Context context, AttributeSet attrs, int defStyle) \{
  54. super(context, attrs, defStyle);
  55. TypedArray typedArray = context.getTheme().obtainStyledAttributes(
  56. attrs, R.styleable.CustomImageView, defStyle, 0);
  57. mTitle = typedArray.getString(typedArray.getIndex(0));//获得自定义属性的title
  58. //获得自定义属性的textSize
  59. mTextSize = typedArray.getDimensionPixelSize(typedArray.getIndex(1),
  60. (int) TypedValue.applyDimension(TypedValue.COMPLEX\_UNIT\_SP, 16,
  61. getResources().getDisplayMetrics()));
  62. //获得自定义属性的textColor
  63. mTextColor = typedArray.getColor(typedArray.getIndex(2), Color.BLACK);
  64. //获得自定义属性的image
  65. mImage = BitmapFactory.decodeResource(getResources(),
  66. typedArray.getResourceId(typedArray.getIndex(3), 0));
  67. //自定义属性的imageScale
  68. mImageScale = typedArray.getInt(typedArray.getIndex(4), 0);
  69. typedArray.recycle();
  70. rect = new Rect();
  71. mPaint = new Paint();
  72. mTextBound = new Rect();
  73. mPaint.setTextSize(mTextSize);
  74. // 计算描绘字体需要的范围
  75. mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);
  76. \}

3、重写onMeasure

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

  1. // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  2. /\*\*
  3. \* 设置自定义View的宽度
  4. \*/
  5. int specMode = MeasureSpec.getMode(widthMeasureSpec);
  6. int specSize = MeasureSpec.getSize(widthMeasureSpec);
  7. if (specMode == MeasureSpec.EXACTLY)// match\_parent , accurate
  8. \{
  9. mWidth = specSize;
  10. \} else \{
  11. // 自定义View的宽度,由左右填充和图片宽度决定
  12. int desireByImg = getPaddingLeft() + getPaddingRight()
  13. + mImage.getWidth();
  14. // 由左右填充和字体绘制范围的宽度决定
  15. int desireByTitle = getPaddingLeft() + getPaddingRight()
  16. + mTextBound.width();
  17. if (specMode == MeasureSpec.AT\_MOST)// wrap\_content
  18. \{
  19. int desire = Math.max(desireByImg, desireByTitle);
  20. mWidth = Math.min(desire, specSize);
  21. \}
  22. \}
  23. /\*\*\*
  24. \* 设置自定义View
  25. \*/
  26. specMode = MeasureSpec.getMode(heightMeasureSpec);
  27. specSize = MeasureSpec.getSize(heightMeasureSpec);
  28. if (specMode == MeasureSpec.EXACTLY)// 设置了明确的值或者是MATCH\_PARENT
  29. \{
  30. mHeight = specSize;
  31. \} else \{
  32. //由上下填充、图片的高度和字体绘制范围的高度决定
  33. int desire = getPaddingTop() + getPaddingBottom()
  34. + mImage.getHeight() + mTextBound.height();
  35. if (specMode == MeasureSpec.AT\_MOST)// wrap\_content
  36. \{
  37. mHeight = Math.min(desire, specSize);
  38. \}
  39. \}
  40. //为控件指定大小
  41. setMeasuredDimension(mWidth, mHeight);
  42. \}

4、重写onDraw

protected void onDraw(Canvas canvas) {

  1. super.onDraw(canvas);
  2. /\*\*
  3. \* 边框属性
  4. \*/
  5. mPaint.setStrokeWidth(4);// 设置画笔宽度
  6. mPaint.setStyle(Paint.Style.STROKE);
  7. mPaint.setColor(Color.CYAN);
  8. canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
  9. rect.left = getPaddingLeft();
  10. rect.right = mWidth - getPaddingRight();
  11. rect.top = getPaddingTop();
  12. rect.bottom = mHeight - getPaddingBottom();
  13. mPaint.setColor(mTextColor);
  14. mPaint.setStyle(Style.FILL);
  15. /\*\*
  16. \* 当前设置的宽度小于字体需要的宽度,将字体改为xxx...
  17. \*/
  18. if (mTextBound.width() > mWidth) \{
  19. TextPaint paint = new TextPaint(mPaint);
  20. String msg = TextUtils.ellipsize(mTitle, paint,
  21. (float) mWidth - getPaddingLeft() - getPaddingRight(),
  22. TextUtils.TruncateAt.END).toString();
  23. canvas.drawText(msg, getPaddingLeft(),
  24. mHeight - getPaddingBottom(), mPaint);
  25. \} else \{
  26. // 正常情况,将字体居中
  27. canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() \* 1.0f / 2,
  28. mHeight - getPaddingBottom(), mPaint);
  29. \}
  30. // 取消使用掉的块
  31. rect.bottom -= mTextBound.height();
  32. if (mImageScale == IMAGE\_SCALE\_FITXY) \{
  33. //绘制image
  34. canvas.drawBitmap(mImage, null, rect, mPaint);
  35. \} else \{
  36. // 计算居中的矩形范围
  37. rect.left = mWidth / 2 - mImage.getWidth() / 2;
  38. rect.right = mWidth / 2 + mImage.getWidth() / 2;
  39. rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight()
  40. / 2;
  41. rect.bottom = (mHeight - mTextBound.height()) / 2
  42. + mImage.getHeight() / 2;
  43. canvas.drawBitmap(mImage, null, rect, mPaint);
  44. \}
  45. \}

做完这些,我们就可以在activity_main.xml文件中引用了





















一共有三种效果:

  • View宽度设置为精确值,字体的长度大于此宽度
  • View宽度设置为wrap_content,字体的宽度大于图片
  • View宽度设置为wrap_content, 字体的宽度小于图片

效果如下:
Center

源代码

参考:
http://blog.csdn.net/lmj623565791/article/details/24300125

发表评论

表情:
评论列表 (有 0 条评论,680人围观)

还没有评论,来说两句吧...

相关阅读