最近,项目中动态展示图片的样式做了调整,宽高比从原来的16:9替换成了2:1。有些地方就要重新计算了。突然觉得,要是ImageView可以自己判断就好了。不想去获取宽度(或者高度),然后利用LayoutParams去修改。
在此基础上,我又加了圆角度数和原型的适配。算是一个小综合吧。
展示图片,我用的Glide。相关Glide,我这里就不做过多解释了。有兴趣的请看
http://blog.csdn.net/u014620028/article/details/78363484
代码实现简单,就直接上代码了
原图:
res\values\styles.xml
<declare-styleable name="MyImageViewRatio">
<attr name="ratio" format="float"/>
<attr name="angle" format="integer"/>
<attr name="isCircle" format="boolean"/>
declare-styleable>
MyImageView
package com.chen.demo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class MyImageView extends ImageView {
//图片的宽高比
private float ratio = 0;
private boolean imgType;
/**
* 圆角的半径
*/
private int mRadius;
/**
* 3x3 矩阵,主要用于缩小放大
*/
private Matrix mMatrix;
/**
* 绘图的Paint
*/
private Paint mBitmapPaint;
/**
* 圆角的大小
*/
private int mBorderRadius;
/**
* 渲染图像,使用图像为绘制图形着色
*/
private BitmapShader mBitmapShader;
private RectF mRoundRect;
private int widthSize;
public MyImageView(Context context) {
this(context, null);
}
public MyImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, -1);
}
public MyImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewRatio);
ratio = ta.getFloat(R.styleable.MyImageViewRatio_ratio, 0);
mBorderRadius = ta.getInteger(R.styleable.MyImageViewRatio_angle, 0);
imgType = ta.getBoolean(R.styleable.MyImageViewRatio_isCircle, false);
ta.recycle();
mMatrix = new Matrix();
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
widthSize = MeasureSpec.getSize(widthMeasureSpec);
/**
* 如果类型是圆形,则强制改变view的宽高一致,以小值为准
*/
if (imgType) {
widthSize = Math.min(getMeasuredWidth(), getMeasuredHeight());
mRadius = widthSize / 2;
setMeasuredDimension(widthSize, widthSize);
} else {
if (ratio != 0) {
// 告诉系统我要申请这么多的宽高
setMeasuredDimension(widthSize, (int) (widthSize / ratio));
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.e("onSizeChanged=", "onSizeChanged");
// 圆角图片的范围
if (!imgType)
mRoundRect = new RectF(0, 0, w, h);
}
@Override
protected void onDraw(Canvas canvas) {
setUpShader();
if (imgType) {
canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);
} else {
canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius, mBitmapPaint);
}
}
/**
* 初始化BitmapShader
*/
private void setUpShader() {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
Bitmap bmp = drawableToBitamp(drawable);
// 将bmp作为着色器,就是在指定区域内绘制bmp
mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP);
float scale = 1.0f;
if (imgType) {
// 拿到bitmap宽或高的小值
int bSize = Math.min(bmp.getWidth(), bmp.getHeight());
scale = widthSize * 1.0f / bSize;
} else {
if (!(bmp.getWidth() == getWidth() && bmp.getHeight() == getHeight())) {
// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
scale = Math.max(getWidth() * 1.0f / bmp.getWidth(),
getHeight() * 1.0f / bmp.getHeight());
}
}
// shader的变换矩阵,我们这里主要用于放大或者缩小
mMatrix.setScale(scale, scale);
// 设置变换矩阵
mBitmapShader.setLocalMatrix(mMatrix);
// 设置shader
mBitmapPaint.setShader(mBitmapShader);
}
/**
* drawable转bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitamp(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
try {
Bitmap bitmap = Bitmap.createBitmap(w, h, drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError outOfMemoryError) {
System.gc();
return BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
}
}
}
image_item.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/item_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:textSize="25sp"/>
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#55ff0000"
/>
<com.chen.demo.MyImageView
android:id="@+id/iv_1"
xmlns:chen="http://schemas.android.com/apk/res/com.chen.demo"
android:layout_width="match_parent"
android:layout_height="60dp"
android:scaleType="fitXY"
chen:angle="50"
chen:ratio="2"
/>
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#5500ff00"
/>
<com.chen.demo.MyImageView
android:id="@+id/iv_2"
xmlns:chen="http://schemas.android.com/apk/res/com.chen.demo"
android:layout_width="match_parent"
android:layout_height="60dp"
android:scaleType="fitXY"
chen:angle="30"
/>
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#550000ff"
/>
<com.chen.demo.MyImageView
android:id="@+id/iv_3"
xmlns:chen="http://schemas.android.com/apk/res/com.chen.demo"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:scaleType="fitXY"
chen:angle="30"
chen:isCircle="true"
chen:ratio="2"
/>
LinearLayout>
在Activity中使用
package com.chen.demo;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
public class MainActivity extends Activity {
private ListView listview;
private String imgUrl = "";
private MyListViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = findViewById(R.id.listview);
imgUrl = "http://pic72.nipic.com/file/20150716/21422793_144600530000_2.jpg";
adapter = new MyListViewAdapter();
listview.setAdapter(adapter);
}
//ListView数据适配器
private class MyListViewAdapter extends BaseAdapter {
@Override
public int getCount() {
return 20;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.image_item, null);
viewHolder = new ViewHolder();
viewHolder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);
viewHolder.iv_1 = (MyImageView) convertView.findViewById(R.id.iv_1);
viewHolder.iv_2 = (MyImageView) convertView.findViewById(R.id.iv_2);
viewHolder.iv_3 = (MyImageView) convertView.findViewById(R.id.iv_3);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.item_tv.setText("item==" + position);
Glide.with(MainActivity.this).load(imgUrl).into(viewHolder.iv_1);
Glide.with(MainActivity.this).load(imgUrl).into(viewHolder.iv_2);
Glide.with(MainActivity.this).load(imgUrl).into(viewHolder.iv_3);
return convertView;
}
private class ViewHolder {
private TextView item_tv;
private MyImageView iv_1;
private MyImageView iv_2;
private MyImageView iv_3;
}
}
}