自定义初学5——自定义View显示图片
前面已经简单介绍过一些自定义View的实现,现在再利用自定义View实现显示一张图片的功能
1、首先编写attrs.xml文件
2、在自定义View中获得我们自定义属性:
public class CustomImageView extends View {
/\*\*
\* 自定义View的宽
\*/
private int mWidth;
/\*\*
\* 自定义View的高
\*/
private int mHeight;
/\*\*
\* 自定义View的图片
\*/
private Bitmap mImage;
/\*\*
\* 图片的缩放模式
\*/
private int mImageScale;
private static final int IMAGE\_SCALE\_FITXY = 0;
private static final int IMAGE\_SCALE\_CENTER = 1;
/\*\*
\* 图片的标题
\*/
private String mTitle;
/\*\*
\* 字体的颜色
\*/
private int mTextColor;
/\*\*
\* 字体的大小
\*/
private int mTextSize;
private Paint mPaint;
/\*\*
\* 文本的绘制范围
\*/
private Rect mTextBound;
/\*\*
\* 需要绘制的整个矩形范围
\*/
private Rect rect;
public CustomImageView(Context context) \{
this(context, null);
\}
public CustomImageView(Context context, AttributeSet attrs) \{
this(context, attrs, 0);
\}
/\*\*
\* 初始化自定义类型
\*
\* @param context
\* @param attrs
\* @param defStyle
\*/
public CustomImageView(Context context, AttributeSet attrs, int defStyle) \{
super(context, attrs, defStyle);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.CustomImageView, defStyle, 0);
mTitle = typedArray.getString(typedArray.getIndex(0));//获得自定义属性的title
//获得自定义属性的textSize
mTextSize = typedArray.getDimensionPixelSize(typedArray.getIndex(1),
(int) TypedValue.applyDimension(TypedValue.COMPLEX\_UNIT\_SP, 16,
getResources().getDisplayMetrics()));
//获得自定义属性的textColor
mTextColor = typedArray.getColor(typedArray.getIndex(2), Color.BLACK);
//获得自定义属性的image
mImage = BitmapFactory.decodeResource(getResources(),
typedArray.getResourceId(typedArray.getIndex(3), 0));
//自定义属性的imageScale
mImageScale = typedArray.getInt(typedArray.getIndex(4), 0);
typedArray.recycle();
rect = new Rect();
mPaint = new Paint();
mTextBound = new Rect();
mPaint.setTextSize(mTextSize);
// 计算描绘字体需要的范围
mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);
\}
3、重写onMeasure
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/\*\*
\* 设置自定义View的宽度
\*/
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match\_parent , accurate
\{
mWidth = specSize;
\} else \{
// 自定义View的宽度,由左右填充和图片宽度决定
int desireByImg = getPaddingLeft() + getPaddingRight()
+ mImage.getWidth();
// 由左右填充和字体绘制范围的宽度决定
int desireByTitle = getPaddingLeft() + getPaddingRight()
+ mTextBound.width();
if (specMode == MeasureSpec.AT\_MOST)// wrap\_content
\{
int desire = Math.max(desireByImg, desireByTitle);
mWidth = Math.min(desire, specSize);
\}
\}
/\*\*\*
\* 设置自定义View
\*/
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// 设置了明确的值或者是MATCH\_PARENT
\{
mHeight = specSize;
\} else \{
//由上下填充、图片的高度和字体绘制范围的高度决定
int desire = getPaddingTop() + getPaddingBottom()
+ mImage.getHeight() + mTextBound.height();
if (specMode == MeasureSpec.AT\_MOST)// wrap\_content
\{
mHeight = Math.min(desire, specSize);
\}
\}
//为控件指定大小
setMeasuredDimension(mWidth, mHeight);
\}
4、重写onDraw
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/\*\*
\* 边框属性
\*/
mPaint.setStrokeWidth(4);// 设置画笔宽度
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.CYAN);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
rect.left = getPaddingLeft();
rect.right = mWidth - getPaddingRight();
rect.top = getPaddingTop();
rect.bottom = mHeight - getPaddingBottom();
mPaint.setColor(mTextColor);
mPaint.setStyle(Style.FILL);
/\*\*
\* 当前设置的宽度小于字体需要的宽度,将字体改为xxx...
\*/
if (mTextBound.width() > mWidth) \{
TextPaint paint = new TextPaint(mPaint);
String msg = TextUtils.ellipsize(mTitle, paint,
(float) mWidth - getPaddingLeft() - getPaddingRight(),
TextUtils.TruncateAt.END).toString();
canvas.drawText(msg, getPaddingLeft(),
mHeight - getPaddingBottom(), mPaint);
\} else \{
// 正常情况,将字体居中
canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() \* 1.0f / 2,
mHeight - getPaddingBottom(), mPaint);
\}
// 取消使用掉的块
rect.bottom -= mTextBound.height();
if (mImageScale == IMAGE\_SCALE\_FITXY) \{
//绘制image
canvas.drawBitmap(mImage, null, rect, mPaint);
\} else \{
// 计算居中的矩形范围
rect.left = mWidth / 2 - mImage.getWidth() / 2;
rect.right = mWidth / 2 + mImage.getWidth() / 2;
rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight()
/ 2;
rect.bottom = (mHeight - mTextBound.height()) / 2
+ mImage.getHeight() / 2;
canvas.drawBitmap(mImage, null, rect, mPaint);
\}
\}
做完这些,我们就可以在activity_main.xml文件中引用了
一共有三种效果:
- View宽度设置为精确值,字体的长度大于此宽度
- View宽度设置为wrap_content,字体的宽度大于图片
- View宽度设置为wrap_content, 字体的宽度小于图片
效果如下:
源代码
参考:
http://blog.csdn.net/lmj623565791/article/details/24300125
还没有评论,来说两句吧...