自定义ViewGroup打造微信朋友圈之九宫图效果
2016-05-10 17:36
489 查看
相信很多朋友用过微博和微信,比如在微博的首页里面有个九宫图的功能,请看下方我截的图,正如你看到的那样可以放九张图片,而且这九张图片拼在一起刚好是一个正方形。需要注意的是当四张图片的时候需要上面下面各两张显示出来。关于九宫图的效果还是挺棒的,我想你们应该都用过。
![](https://img-blog.csdn.net/20160322134423414?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
今天我来不是介绍九宫图的,正如本次博客标题所说的那样
我今天想从Android开发的角度来剖析九宫图是怎么实现的。
想要做成这种效果,我想到有两种方法
1.官方提供的GridView控件
2.自定义九宫图控件
先说说第1种: ListView嵌套GridView ,然后在ListView的Adapter中的getView方法里设置
GridView的Adapter,其实就是要更新GridView的内容,这种做法ListView在滑动的时候会出现明显的卡顿。
我之用的是这种方法,发现不满意。原生的轮子满足不了你,咱们自己来造一个满足自己。
再说说第2种是自定义控件,接着想是继承View呢?还是继承ViewGroup呢?继承View你可以把九宫图
想象成一个控件,然后把图片Draw出来。继承ViewGroup的话你可以把九宫图想象成一个容器,里面再包含九个
ImageView控件就行了。说到这里,聪明的你是不是快有思路了。
OK下面开始谈谈怎样通过继承ViewGroup来打造属于自己的九宫图效果。
[java] view
plain copy
print?
/**
* 朋友圈九宫图控件
* @author manymore13
* @blog http://blog.csdn.net/manymore13/
*/
public class MultyPicView extends ViewGroup {
/**
* 单行最多图片数
*/
public final static int LINE_MAX_COUNT = 3;
/**
* 这里是九宫图
*/
public final static int MAX_IMG_COUNT = 9;
/**
* 每行最大图片数
*/
public int mLineMaxCount = LINE_MAX_COUNT;
/**
* 图片地址
*/
private String[] mImgUrls;
/**
* 图片的数量
*/
private int mImgCount;
/**
* 图片之间的间距
*/
private int mPicSpace = 5;
/**
* 子view边长度
*/
private int mChildEdgeSize;
/**
* 子view可见个数
*/
private int mChildVisibleCount;
/**
* 这里是九宫格 所以设置为数值9
*/
private int mMaxChildCount = MAX_IMG_COUNT;
/**
* 是否截断点击事件
*/
private boolean mIntercept = false;
/**
* 服务器上缩略图最大尺寸
*/
private static final int maxPicSize = 250;
/**
* 单张图片宽度
*/
private int mSingleSrcWidth;
/**
* 单张图片高度
*/
private int mSingleSrcHeight;
/**
* 单张图片时控件期望的边的最大的大小
*/
private int mSingleExpectMaxViewSize;
private float mSingleExpectMaxViewRatio = 0.8f;
/**
* 单张图片时图片缩放比例
*/
private float mSingleScaleRatio;
/**
* 各个图片点击事件回调
*/
private ClickCallback mClickCallback;
private DisplayImageOptions mOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.bitmapConfig(Bitmap.Config.ARGB_8888)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT).build();
private ImageLoader mLoader = ImageLoader.getInstance();
private OnClickListener mClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (v instanceof ImageView) {
Integer index = (Integer) v.getTag();
if (mClickCallback != null) {
mClickCallback.callback(index, mImgUrls);
}
}
}
};
public MultyPicView(Context context) {
super(context);
}
public MultyPicView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.multy_pic_view, 0, 0);
int len = a.getIndexCount();
// 获取自定义属性
for (int i = 0; i < len; i++) {
int attr = a.getIndex(i);
if (attr == R.styleable.multy_pic_view_pic_space) {
float mul = a.getFloat(attr, 1.0f);
mPicSpace = DeviceUtils.dp2px(mul, getContext());
}
}
mSingleExpectMaxViewSize = Math.min(DeviceUtils.getScreenHeight((Activity) getContext()),
DeviceUtils.getScreenWidth((Activity) getContext()));
mSingleExpectMaxViewSize = (int) (mSingleExpectMaxViewSize
* mSingleExpectMaxViewRatio);
a.recycle();
}
/**
* 初始化该控件
*
* @param len
*/
public void setMaxChildCount(int len) {
removeAllViews();
mMaxChildCount = len;
for (int i = 0; i < len; i++) {
ImageViewChangeBg iv = new ImageViewChangeBg(getContext());
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv.setOnClickListener(mClickListener);
iv.setTag(i);
this.addView(iv, params);
}
}
public String[] getImgUrl() {
return mImgUrls;
}
/**
* 单张图时调用 ,注意 这里宽高需要服务器提供
* 因为在你下载图片时是不知道图片大小的
* 所以需要服务器告诉你
*
* @param imgUrl 图片地址
* @param srcWidth 图片宽度
* @param srcHeight 图片高度
*/
public void setSingleImg(String imgUrl, int srcWidth, int srcHeight) {
mLineMaxCount = 1;
int maxSize = Math.max(srcWidth, srcHeight);
mSingleScaleRatio = 1f;
if (maxSize > mSingleExpectMaxViewSize) {
mSingleScaleRatio = maxSize * 1.0f / mSingleExpectMaxViewSize;
}
mSingleSrcWidth = (int) (srcWidth / mSingleScaleRatio);
mSingleSrcHeight = (int) (srcHeight / mSingleScaleRatio);
boolean request = false;
mImgUrls = new String[]{imgUrl};
if (mImgUrls != null && mImgUrls.length == 1) {
request = true;
}
dealWithImgs(mImgUrls);
if (request) {
this.requestLayout();
}
}
/**
* 显示多张图片(两张以上)图片 传图片数组进去
* 你在外部使用时需要把图片传进去
* @param imgs 图片url数组
*/
public void setImgs(String[] imgs) {
mLineMaxCount = LINE_MAX_COUNT;
mSingleSrcHeight = mSingleSrcWidth = 0;
mSingleScaleRatio = 1;
dealWithImgs(imgs);
}
/**
* 设置是否拦截事件
*
* @param intercept true 事件拦截
*/
public void setIntercept(boolean intercept) {
mIntercept = intercept;
}
/**
* 设置图片点击回调
*
* @param callback 事件回调
*/
public void setClickCallback(ClickCallback callback) {
mClickCallback = callback;
}
/**
* 点击图片回调
*/
public interface ClickCallback {
/**
* 回调方法
* @param index 点击的索引
2496b
* @param str 图片地址数组
*/
void callback(int index, String[] str);
}
/**
* 获取图片可能显示多少行数
* @param imgSize 图片个数
* @return 行数
*/
public int getMultyImgLines(int imgSize) {
if (imgSize == 0) {
return 1;
}
return (imgSize + mLineMaxCount - 1) / mLineMaxCount;
}
/**
* 获取当前图片数量
*
* @return 数量
*/
public int getImgCount() {
return mImgCount;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mIntercept;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int lpadding = getPaddingLeft();
int tpadding = getPaddingTop();
int left = lpadding, top = tpadding;
int childCount = getChildCount();
int visibleChildCount = mChildVisibleCount;
int breakLineC = 0; // 断行
if (visibleChildCount == 4) {
// 当四张图片时 两张时换行
breakLineC = 2;
} else {
// 每行三张图片换行
breakLineC = mLineMaxCount;
}
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
if (visibleChildCount == 1) {
// 单张做特殊显示
if (mLineMaxCount == 1) {
// left = (getMeasuredWidth() - mSingleSrcWidth) / 2;// 居中
left = lpadding; // 居左
}
if (mSingleSrcWidth == 0 || mSingleSrcHeight == 0) {
child.layout(left, top, left + mChildEdgeSize,
top + mChildEdgeSize);
} else {
child.layout(left, top, left + mSingleSrcWidth,
top + mSingleSrcHeight);
}
} else {
child.layout(left, top, left + mChildEdgeSize,
top + mChildEdgeSize);
left += (mPicSpace + mChildEdgeSize);
if ((i + 1) % breakLineC == 0) {
top += mChildEdgeSize + mPicSpace;
left = lpadding;
}
}
}
}
/**
* 确定九宫图控件自身的大小以及内部ImageView的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getChildCount() == 0) {
setMaxChildCount(mMaxChildCount);
}
measureImgWidth(widthMeasureSpec);
mChildVisibleCount = getVisibleChildCount();
int lines = getMultyImgLines(mChildVisibleCount);
int viewHeight = ((lines - 1) * mPicSpace + lines * mChildEdgeSize)
+ getPaddingTop() + getPaddingBottom();
if (mChildVisibleCount == 1) {
viewHeight = mSingleSrcHeight == 0 ? viewHeight : mSingleSrcHeight;
}
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(widthSize, viewHeight);
int heightSize = mChildEdgeSize;
widthSize = heightSize;
if (mChildVisibleCount == 1 && mSingleSrcWidth != 0) {
widthSize = mSingleSrcWidth;
heightSize = mSingleSrcHeight;
}
measureChildren(widthSize, heightSize);
}
/**
* 计算图片的大小
* @param widthMeasureSpec
*/
protected void measureImgWidth(int widthMeasureSpec) {
if (mChildEdgeSize == 0) {
int measureSize = MeasureSpec.getSize(widthMeasureSpec);
mChildEdgeSize = (measureSize - (LINE_MAX_COUNT - 1) * mPicSpace
- getPaddingLeft() - getPaddingRight()) / LINE_MAX_COUNT;
}
}
/**
* 获取可见图片数量
*/
private int getVisibleChildCount() {
int childCount = getChildCount();
int count = 0;
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).getVisibility() != View.GONE) {
count++;
}
}
return count;
}
/**
* 处理图片
*
* @param imgs 图片地址列表
*/
private void dealWithImgs(String[] imgs) {
if (imgs == null || imgs.length == 0) {
return;
}
mImgUrls = imgs;
mImgCount = imgs.length;
int imgLen = mImgCount;
int maxChildCount = mMaxChildCount;
for (int i = 0; i < maxChildCount; i++) {
final ImageView chileIv = (ImageView) getChildAt(i);
if (i < imgLen) {
chileIv.setVisibility(View.VISIBLE);
String url = imgs[i];
ImageSize imageSize = null;
if (i == 0 && mImgCount == 1 && mSingleSrcWidth != 0
&& mSingleSrcWidth != 0) {
imageSize = new ImageSize(mSingleSrcWidth, mSingleSrcHeight);
} else {
imageSize = new ImageSize(maxPicSize, maxPicSize);
}
loadImg(url, imageSize, chileIv);
} else {
chileIv.setVisibility(View.GONE);
}
}
}
private void loadImg(String url, ImageSize imageSize, final ImageView chileIv) {
mLoader.displayImage(url,chileIv);
}
}
我画了一张九宫图控件的简易图,最外层蓝色边框所包含的区域表示的是九宫图控件的区域。
通过这张图 可以很好的算出图片大小以及它的位置
先确定九宫图控件大小 它的宽度由父容器决定,它的父容器给他多宽我就设置它多宽;
宽度知道了后就可以确定其内部图片控件的宽高 由于图片控件是正方形的所以它的边长是 (MultyViewWidth - paddingleft - paddingRight - 2*picSpace) / 3 详情请看measureImgWidth方法 边长知道了求它的位置坐标 这完全是初中数学,我这里就不作详细讲解,你可以参考onlayout方法中的解法。
![](https://img-blog.csdn.net/20160323134357021?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
上面是模拟器截取的动态图(图片做了压缩处理) 看起来有点卡,其实在真机上运行的很流畅。图中黑边是ListView的分割线
好了今天就写这么多,这篇博客你可能几分钟就看完了,台上一分钟,台下十年功,写一篇博客也是一样要花不少时间,整理啊构思啊 写Demo啊。所以如果你读完觉得有那么点用处,那请你帮我点个赞。
转载的请注明出处来自manymore13
今天我来不是介绍九宫图的,正如本次博客标题所说的那样
我今天想从Android开发的角度来剖析九宫图是怎么实现的。
想要做成这种效果,我想到有两种方法
1.官方提供的GridView控件
2.自定义九宫图控件
先说说第1种: ListView嵌套GridView ,然后在ListView的Adapter中的getView方法里设置
GridView的Adapter,其实就是要更新GridView的内容,这种做法ListView在滑动的时候会出现明显的卡顿。
我之用的是这种方法,发现不满意。原生的轮子满足不了你,咱们自己来造一个满足自己。
再说说第2种是自定义控件,接着想是继承View呢?还是继承ViewGroup呢?继承View你可以把九宫图
想象成一个控件,然后把图片Draw出来。继承ViewGroup的话你可以把九宫图想象成一个容器,里面再包含九个
ImageView控件就行了。说到这里,聪明的你是不是快有思路了。
OK下面开始谈谈怎样通过继承ViewGroup来打造属于自己的九宫图效果。
[java] view
plain copy
print?
/**
* 朋友圈九宫图控件
* @author manymore13
* @blog http://blog.csdn.net/manymore13/
*/
public class MultyPicView extends ViewGroup {
/**
* 单行最多图片数
*/
public final static int LINE_MAX_COUNT = 3;
/**
* 这里是九宫图
*/
public final static int MAX_IMG_COUNT = 9;
/**
* 每行最大图片数
*/
public int mLineMaxCount = LINE_MAX_COUNT;
/**
* 图片地址
*/
private String[] mImgUrls;
/**
* 图片的数量
*/
private int mImgCount;
/**
* 图片之间的间距
*/
private int mPicSpace = 5;
/**
* 子view边长度
*/
private int mChildEdgeSize;
/**
* 子view可见个数
*/
private int mChildVisibleCount;
/**
* 这里是九宫格 所以设置为数值9
*/
private int mMaxChildCount = MAX_IMG_COUNT;
/**
* 是否截断点击事件
*/
private boolean mIntercept = false;
/**
* 服务器上缩略图最大尺寸
*/
private static final int maxPicSize = 250;
/**
* 单张图片宽度
*/
private int mSingleSrcWidth;
/**
* 单张图片高度
*/
private int mSingleSrcHeight;
/**
* 单张图片时控件期望的边的最大的大小
*/
private int mSingleExpectMaxViewSize;
private float mSingleExpectMaxViewRatio = 0.8f;
/**
* 单张图片时图片缩放比例
*/
private float mSingleScaleRatio;
/**
* 各个图片点击事件回调
*/
private ClickCallback mClickCallback;
private DisplayImageOptions mOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.bitmapConfig(Bitmap.Config.ARGB_8888)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT).build();
private ImageLoader mLoader = ImageLoader.getInstance();
private OnClickListener mClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (v instanceof ImageView) {
Integer index = (Integer) v.getTag();
if (mClickCallback != null) {
mClickCallback.callback(index, mImgUrls);
}
}
}
};
public MultyPicView(Context context) {
super(context);
}
public MultyPicView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.multy_pic_view, 0, 0);
int len = a.getIndexCount();
// 获取自定义属性
for (int i = 0; i < len; i++) {
int attr = a.getIndex(i);
if (attr == R.styleable.multy_pic_view_pic_space) {
float mul = a.getFloat(attr, 1.0f);
mPicSpace = DeviceUtils.dp2px(mul, getContext());
}
}
mSingleExpectMaxViewSize = Math.min(DeviceUtils.getScreenHeight((Activity) getContext()),
DeviceUtils.getScreenWidth((Activity) getContext()));
mSingleExpectMaxViewSize = (int) (mSingleExpectMaxViewSize
* mSingleExpectMaxViewRatio);
a.recycle();
}
/**
* 初始化该控件
*
* @param len
*/
public void setMaxChildCount(int len) {
removeAllViews();
mMaxChildCount = len;
for (int i = 0; i < len; i++) {
ImageViewChangeBg iv = new ImageViewChangeBg(getContext());
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv.setOnClickListener(mClickListener);
iv.setTag(i);
this.addView(iv, params);
}
}
public String[] getImgUrl() {
return mImgUrls;
}
/**
* 单张图时调用 ,注意 这里宽高需要服务器提供
* 因为在你下载图片时是不知道图片大小的
* 所以需要服务器告诉你
*
* @param imgUrl 图片地址
* @param srcWidth 图片宽度
* @param srcHeight 图片高度
*/
public void setSingleImg(String imgUrl, int srcWidth, int srcHeight) {
mLineMaxCount = 1;
int maxSize = Math.max(srcWidth, srcHeight);
mSingleScaleRatio = 1f;
if (maxSize > mSingleExpectMaxViewSize) {
mSingleScaleRatio = maxSize * 1.0f / mSingleExpectMaxViewSize;
}
mSingleSrcWidth = (int) (srcWidth / mSingleScaleRatio);
mSingleSrcHeight = (int) (srcHeight / mSingleScaleRatio);
boolean request = false;
mImgUrls = new String[]{imgUrl};
if (mImgUrls != null && mImgUrls.length == 1) {
request = true;
}
dealWithImgs(mImgUrls);
if (request) {
this.requestLayout();
}
}
/**
* 显示多张图片(两张以上)图片 传图片数组进去
* 你在外部使用时需要把图片传进去
* @param imgs 图片url数组
*/
public void setImgs(String[] imgs) {
mLineMaxCount = LINE_MAX_COUNT;
mSingleSrcHeight = mSingleSrcWidth = 0;
mSingleScaleRatio = 1;
dealWithImgs(imgs);
}
/**
* 设置是否拦截事件
*
* @param intercept true 事件拦截
*/
public void setIntercept(boolean intercept) {
mIntercept = intercept;
}
/**
* 设置图片点击回调
*
* @param callback 事件回调
*/
public void setClickCallback(ClickCallback callback) {
mClickCallback = callback;
}
/**
* 点击图片回调
*/
public interface ClickCallback {
/**
* 回调方法
* @param index 点击的索引
2496b
* @param str 图片地址数组
*/
void callback(int index, String[] str);
}
/**
* 获取图片可能显示多少行数
* @param imgSize 图片个数
* @return 行数
*/
public int getMultyImgLines(int imgSize) {
if (imgSize == 0) {
return 1;
}
return (imgSize + mLineMaxCount - 1) / mLineMaxCount;
}
/**
* 获取当前图片数量
*
* @return 数量
*/
public int getImgCount() {
return mImgCount;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mIntercept;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int lpadding = getPaddingLeft();
int tpadding = getPaddingTop();
int left = lpadding, top = tpadding;
int childCount = getChildCount();
int visibleChildCount = mChildVisibleCount;
int breakLineC = 0; // 断行
if (visibleChildCount == 4) {
// 当四张图片时 两张时换行
breakLineC = 2;
} else {
// 每行三张图片换行
breakLineC = mLineMaxCount;
}
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
if (visibleChildCount == 1) {
// 单张做特殊显示
if (mLineMaxCount == 1) {
// left = (getMeasuredWidth() - mSingleSrcWidth) / 2;// 居中
left = lpadding; // 居左
}
if (mSingleSrcWidth == 0 || mSingleSrcHeight == 0) {
child.layout(left, top, left + mChildEdgeSize,
top + mChildEdgeSize);
} else {
child.layout(left, top, left + mSingleSrcWidth,
top + mSingleSrcHeight);
}
} else {
child.layout(left, top, left + mChildEdgeSize,
top + mChildEdgeSize);
left += (mPicSpace + mChildEdgeSize);
if ((i + 1) % breakLineC == 0) {
top += mChildEdgeSize + mPicSpace;
left = lpadding;
}
}
}
}
/**
* 确定九宫图控件自身的大小以及内部ImageView的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getChildCount() == 0) {
setMaxChildCount(mMaxChildCount);
}
measureImgWidth(widthMeasureSpec);
mChildVisibleCount = getVisibleChildCount();
int lines = getMultyImgLines(mChildVisibleCount);
int viewHeight = ((lines - 1) * mPicSpace + lines * mChildEdgeSize)
+ getPaddingTop() + getPaddingBottom();
if (mChildVisibleCount == 1) {
viewHeight = mSingleSrcHeight == 0 ? viewHeight : mSingleSrcHeight;
}
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(widthSize, viewHeight);
int heightSize = mChildEdgeSize;
widthSize = heightSize;
if (mChildVisibleCount == 1 && mSingleSrcWidth != 0) {
widthSize = mSingleSrcWidth;
heightSize = mSingleSrcHeight;
}
measureChildren(widthSize, heightSize);
}
/**
* 计算图片的大小
* @param widthMeasureSpec
*/
protected void measureImgWidth(int widthMeasureSpec) {
if (mChildEdgeSize == 0) {
int measureSize = MeasureSpec.getSize(widthMeasureSpec);
mChildEdgeSize = (measureSize - (LINE_MAX_COUNT - 1) * mPicSpace
- getPaddingLeft() - getPaddingRight()) / LINE_MAX_COUNT;
}
}
/**
* 获取可见图片数量
*/
private int getVisibleChildCount() {
int childCount = getChildCount();
int count = 0;
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).getVisibility() != View.GONE) {
count++;
}
}
return count;
}
/**
* 处理图片
*
* @param imgs 图片地址列表
*/
private void dealWithImgs(String[] imgs) {
if (imgs == null || imgs.length == 0) {
return;
}
mImgUrls = imgs;
mImgCount = imgs.length;
int imgLen = mImgCount;
int maxChildCount = mMaxChildCount;
for (int i = 0; i < maxChildCount; i++) {
final ImageView chileIv = (ImageView) getChildAt(i);
if (i < imgLen) {
chileIv.setVisibility(View.VISIBLE);
String url = imgs[i];
ImageSize imageSize = null;
if (i == 0 && mImgCount == 1 && mSingleSrcWidth != 0
&& mSingleSrcWidth != 0) {
imageSize = new ImageSize(mSingleSrcWidth, mSingleSrcHeight);
} else {
imageSize = new ImageSize(maxPicSize, maxPicSize);
}
loadImg(url, imageSize, chileIv);
} else {
chileIv.setVisibility(View.GONE);
}
}
}
private void loadImg(String url, ImageSize imageSize, final ImageView chileIv) {
mLoader.displayImage(url,chileIv);
}
}
在MultyPicView类中,大家可以看到里面用到ImageLoader框架来管理图片的三缓存,当然你也可以用其他的框架来管理。 构造函数里获取自定义属性值 pic_space,这是图片之间的间距值。浮点型
紧接着调用setMaxChildCount进行九宫图的初始化工作 存放ImageView 早期存储起来,后面用的时候就不需要再创建新的控件对象。
setImgs方法是你在Adapter的getView方法中需要把相应图片的url数组传进去即可 如果你是一张图片的话请调用 setSingleImg方法。
另外onLayout和onMeasure是本次博客的一个关键点。
会自定义控件的同学都知道这两个方法
onLayout是ViewGroup中的方法,它的用处是告诉系统确定View本身的位置,以及确定容器内部View的位置,
而onMeasure是View中的方法测量View本身的大小 如果你的控件是容器的话 那还要测量其内部View的大小。
说了他们的用处后,下面我讲解下该怎么样确认每张图片View的位置以及大小。
我画了一张九宫图控件的简易图,最外层蓝色边框所包含的区域表示的是九宫图控件的区域。
通过这张图 可以很好的算出图片大小以及它的位置
先确定九宫图控件大小 它的宽度由父容器决定,它的父容器给他多宽我就设置它多宽;
宽度知道了后就可以确定其内部图片控件的宽高 由于图片控件是正方形的所以它的边长是 (MultyViewWidth - paddingleft - paddingRight - 2*picSpace) / 3 详情请看measureImgWidth方法 边长知道了求它的位置坐标 这完全是初中数学,我这里就不作详细讲解,你可以参考onlayout方法中的解法。
上面是模拟器截取的动态图(图片做了压缩处理) 看起来有点卡,其实在真机上运行的很流畅。图中黑边是ListView的分割线
好了今天就写这么多,这篇博客你可能几分钟就看完了,台上一分钟,台下十年功,写一篇博客也是一样要花不少时间,整理啊构思啊 写Demo啊。所以如果你读完觉得有那么点用处,那请你帮我点个赞。
转载的请注明出处来自manymore13
相关文章推荐
- 社交巨头三国杀:微信、WhatsApp、Line到底有啥区别?
- 微信悄悄升级群聊功能:个人微信营销号的福音
- 突击部队拼多多
- 我是运营,我没有假期
- 如何做到日消息量100万的微信公众号?
- 论微信取消推送功能的可能性(原创)
- 微信的成功,靠的是QQ导流吗?
- 「Linux 中国」2018 微信文章排行榜
- 马化腾亲自“站台” 企业微信和个人微信互通能带来什么?
- 一个微信群的兴亡
- 微信服务号推送模板消息接口
- PHP限制页面只能在微信自带浏览器访问的代码
- HTML5实现微信拍摄上传照片功能
- 微信小程序去哪里找 小程序到底如何使用(附小程序名单)
- 使用jQuery.wechat构建微信WEB应用
- 使用JavaScript脚本判断页面是否在微信中被打开
- nw.js实现类似微信的聊天软件