Giter Site home page Giter Site logo

laobie / ninegridimageview Goto Github PK

View Code? Open in Web Editor NEW
1.4K 33.0 235.0 202 KB

A custom widget for Android, which used for showing grid pictures.

Home Page: http://t.cn/RGH3uNF

License: Apache License 2.0

Java 100.00%
ninegridview showing-grid-pictures custom-widget android

ninegridimageview's Issues

在特殊情况图片循环被加载。

使用的时候,在三星note4手机,展示6张图片。其中有2张图片会重复加载,图片加载用imageloader。现象是,图片被加载出来就重新再次加载。发生的概率比较小。怀疑是图片展示的回调接口重复调用。

如果图片地址错误,设置一个错误显示的位图,会导致```onDisplayImage```不停重复调用

如果图片地址错误,设置一个错误显示的位图,会导致onDisplayImage不停重复调用。
把Demo中的加载图片的这段

Picasso.with(context).load(s).placeholder(R.drawable.ic_default_image).into(imageView);

改成

Picasso.with(context).load(s).error(R.drawable.ic_default_image).into(imageView);

再把图片地址换成一个错误的,就能复现了。

Picasso 和 Glide 都有这种问题。

水平有限不知道什么原因,还希望作者看看

当图片没有的时候出现错乱

考虑当图片没有的时候,recyclerView会出现错乱,这个算是一个改进建议吧~作为ViewGroup,在bind的时候因为是动态添加子view的,首先调用removeAllViews或者判断一下list的size是否妥当写些?

在第二次调用setImagesData后mImgDataList的大小变得跟传入的数据大小一致

int oldShowCount = getNeedShowCount(mImgDataList.size());
if (oldShowCount > newShowCount) {
removeViews(newShowCount, oldShowCount - newShowCount);
} else if (oldShowCount < newShowCount) {
for (int i = oldShowCount; i < newShowCount; i++) {
ImageView iv = getImageView(i);
if (iv == null) {
return;
}
addView(iv, generateDefaultLayoutParams());
}
}
这段代码不会执行,造成崩溃

onItemImageClick返回的list

protected void onItemImageClick(Context context, int index, List<String> list)
这里的list,目前是返回了显示在屏幕上的list,不应该是原始list吗
比如我的lis是12个元素,但是我默认只显示9个,点击之后才跳到新页面来显示所有的元素

或者说回调多一个参数呢,比如变成
protected void onItemImageClick(Context context, int index, List<String> list,List<String> initList)

滑动时,会出现九宫格控件中的部分图片被放大的效果

猴哥,现在遇到这个情况,我现在测试数据的时候让总的数据集大于九张,那么就会有几个item都是显示九张图片,但是会出现下面的情况?这种情况的复现是:缓慢滑动到最后底部,就会出现这个问题(有时候快速滑动也会出现这个问题),来回滑动到上一个正常的九张图片再滑回来就正常了
ques123
gif太大上传不了。。。
eeff

adjustresize模式下RecyclerView中键盘弹出收回造成布局没有被重绘

这种情况只在外边包裹一层或多层view group时发生,on measure没有调用,但是父布局的是调用了的,只能forcelayout暂时解决。复现场景是,在demo中添加一个edittext位于recyclerview下边,activity修改为adjustresize,键盘弹起,窗口resize,奇数次,这时候该控件不会重新布局

item监听为什么放在adapter中啊?

一般控件的监听不应该是类似 listview.setOnItemClickListener()么,是通过控件来设置item监听的。这个库是放在adapter中的,为什么这么做呢?

请教个问题

你好,我现在的需求需要在图片上显示视频的类型
image

我在这个地方直接inflate的一个view, 是个 FrameLayout,里面有2个imageview,其它地方也都改了,现在里面的2个imageview不能正常显示,请问下是什么原因,谢谢

断点调试,发现无法实现复用

作者你好,在调试您的这个九宫格控件的时候遇到些问题。假设列表中第一个item中有一张图片,第二个item有三张图片。发现mImgDataList第一次为null,这个时候就可以添加imageview布局将图片显示上去,当显示第二个item时,按理说这个时候mImgDataList的size为1了,就应该走else语句了,去再new两个imageview即可。但是断点调试的结果是,显示第二个item的时候,走这个if-else语句时,mImgDataList仍为null。这样的话就相当于new三个imageview,无法重用。如下图
quest
希望作者能抽时间解答下,谢谢~

我用baserecyclerviewadapterhelper适配时,引用此控件,在6.0系统上 报ninegridview.GridImageView{c03dd20 V.ED..C.. ......ID 0,312-300,612} during layout: running second layout pass

public class HealthAdapter extends BaseQuickAdapter<HealthInfo, BaseViewHolder> {

public HealthAdapter(@LayoutRes int layoutResId, @Nullable ArrayList<HealthInfo> data) {
    super(layoutResId, data);
}
NineGridImageViewAdapter<String> mAdapter = new NineGridImageViewAdapter<String>() {
    @Override
    protected void onDisplayImage(Context context, ImageView imageView, String s) {
        Glide.with(mContext)
                .load(s)
                .placeholder(R.mipmap.load_logo)
                .error(R.mipmap.load_logo)
                .dontAnimate()
                .into(imageView);
    }

    @Override
    protected ImageView generateImageView(Context context) {
        return super.generateImageView(context);
    }

    @Override
    protected void onItemImageClick(Context context, ImageView imageView, int index, List<String> list) {

    }
};
@Override
protected void convert(BaseViewHolder helper, HealthInfo item) {


    List<String>  url=new ArrayList<>();
    url.add("http://ac-QYgvX1CC.clouddn.com/ad99de83e1e3f7d4.jpg");
    url.add("http://ac-QYgvX1CC.clouddn.com/ad99de83e1e3f7d4.jpg");
    url.add("http://ac-QYgvX1CC.clouddn.com/ad99de83e1e3f7d4.jpg");
    url.add("http://ac-QYgvX1CC.clouddn.com/ad99de83e1e3f7d4.jpg");
    TextView  tvTime=helper.getView(R.id.tv_time);
    TextView  tvKind=helper.getView(R.id.tv_kind);
    TextView  tvHospital=helper.getView(R.id.tv_hospital);
    NineGridImageView<String> mNglContent =helper.getView(R.id.ngl_images);

    mNglContent.setAdapter(mAdapter);
    mNglContent.setImagesData(url);
    String date=item.getPre_date().substring(0,10);
    tvTime.setText(date);
    tvKind.setText(item.getMedical_type().equals("0")?"11111":"22222");
    tvHospital.setText("机构:"+item.getOrg_name());


}

针对同一个NineGridImageView对它多次赋值报错了

打了几行日志:

public void setImagesData(List lists) {
        try {
            if (lists == null || lists.isEmpty()) {
                LogUtil.d(TAG, "setImagesData debug, New List = NULL");
                this.setVisibility(GONE);
                return;
            } else {
                LogUtil.d(TAG, "setImagesData debug, New List != NULL, Size = " + lists.size());
                this.setVisibility(VISIBLE);
            }
            LogUtil.d(TAG, "setImagesData debug, Max Size = " + mMaxSize);
            if (mMaxSize > 0 && lists.size() > mMaxSize) {
                lists = lists.subList(0, mMaxSize);
            }
            LogUtil.d(TAG, "setImagesData debug, Show Style = " + mShowStyle);
            int[] gridParam = calculateGridParam(lists.size(), mShowStyle);
            mRowCount = gridParam[0];
            mColumnCount = gridParam[1];
            LogUtil.d(TAG, "setImagesData debug, Row Count = " + mRowCount);
            LogUtil.d(TAG, "setImagesData debug, Column Count = " + mColumnCount);
            if (mImgDataList == null) {
                LogUtil.d(TAG, "setImagesData debug, Old List = NULL");
                int i = 0;
                while (i < lists.size()) {
                    GFImageView iv = getImageView(i);
                    if (iv == null) {
                        return;
                    }
                    addView(iv, generateDefaultLayoutParams());
                    i++;
                }
            } else {
                LogUtil.d(TAG, "setImagesData debug, Old List != NULL");
                int oldViewCount = mImgDataList.size();
                int newViewCount = lists.size();
                if (oldViewCount > newViewCount) {
                    removeViews(newViewCount, oldViewCount - newViewCount);
                } else if (oldViewCount < newViewCount) {
                    for (int i = oldViewCount; i < newViewCount; i++) {
                        GFImageView iv = getImageView(i);
                        if (iv == null) {
                            return;
                        }
                        addView(iv, generateDefaultLayoutParams());
                    }
                }
            }
            mImgDataList = lists;
            requestLayout();
        } catch (Exception e) {
            LogUtil.e(TAG, "setImagesData error", e);
        }
    }

日志输出如下:

04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, New List != NULL, Size = 6
04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, Max Size = 9
04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, Show Style = 1
04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, Row Count = 2
04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, Column Count = 3
04-18 20:56:51.837 19831-19831/NineGridImageView: setImagesData debug, Old List != NULL
04-18 20:56:51.838 19831-19831/NineGridImageView: setImagesData error
java.lang.IllegalStateException: **The specified child already has a parent. You must call removeView() on the child's parent first.**
at android.view.ViewGroup.addViewInner(ViewGroup.java:4315)
at android.view.ViewGroup.addView(ViewGroup.java:4151)
at android.view.ViewGroup.addView(ViewGroup.java:4123)
at com.way.heard.ui.views.NineGridImageView.setImagesData(NineGridImageView.java:155)
at com.way.heard.ui.activities.WritingActivity$7.onHanlderSuccess(WritingActivity.java:286)
at cn.finalteam.galleryfinal.PhotoBaseActivity.resultData(PhotoBaseActivity.java:186)
at cn.finalteam.galleryfinal.PhotoSelectActivity.onClick(PhotoSelectActivity.java:390)
at android.view.View.performClick(View.java:5226)
at android.view.View$PerformClick.run(View.java:21265)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5845)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)

等我解决了过来Comment一下。


来了,mImgDataList的值会莫名其妙的丢失,导致
mImgDataList.size() = 0;
好在博主方法里也没用到mImgDataList里的数据,只用到了size(),用一个静态变量保存一下**size()**的值即可。

能否不控制图片9张的上限

能否不限制图片上限,我在NineGridImageView中把下面的注释了就好了,因为如果做一个时间轴的demo,不能保证每一个item最多9张图,或者超过了9张提供接口控制。
if (lists.size() > 9) {
lists = lists.subList(0, 9);
}
另外图片的点击背景效果最好可以提供接口修改。

咨询个问题

在使用的过程中,看到日志中不停的打印出requestLayout,我想问一下这样产生的原因是什么,对性能会不会有很大的影响?

Glide加载不出来图片???

一直显示占位图,退出再进去才正常显示。弱弱的问下,这个项目作者还更新么。看到好多问题都很久了。。。 (ಥ﹏ಥ)

转场动画的实现

需要做点击图片查看详情的时候,有个放大缩小的功能,那就要获取到当前的ImageView,onItemImageClick能返回这个View吗

关于 使用 Glide 用了 placeholder 死循环解决方案

@OverRide
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("loadSquareSmallWallpaperData", "changed=" + changed + ",isonDetachedFromWindow=" + isDetachedFromWindow);
if (changed || isReDraw) {
isReDraw = false;
layoutChildrenView();
}
}

boolean isDetachedFromWindow = false;
boolean isReDraw = false;

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    isDetachedFromWindow = true;
    Log.i("loadSquareSmallWallpaperData", "onDetachedFromWindow");
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (isDetachedFromWindow) {
        isDetachedFromWindow = false;
        isReDraw = true;

    }
    Log.i("loadSquareSmallWallpaperData", "onAttachedToWindow");
}

关闭日志

你的日志怎么关闭了,一直在打印

使用Glide不能下载图片,Picasso可以

// Picasso.with(context)
// .load(o.getUrl())
// .placeholder(R.mipmap.default_no_order)
// .into(imageView);

            GlideApp.with(context)
                    .load(o.getUrl())
                    .transition(new DrawableTransitionOptions().dontTransition())
                    .apply(getRequestOptions())
                    .into(imageView);

singleSize的大小最好有个判断

singleImgSize的大小最好有个判断
当xml中定义的大小超过屏幕尺寸的时候,用屏幕尺寸大小
不然的话xml中定义非常大的时候,显示是不合理的

自定义图片宽高比例实现

首先还是感谢作者提供的开源项目!因为我的图片需要实现的图片不是正方形,而作者的图片都是正方形的。所以,修改了一下,支持可以使用宽高比例图片。大家如果有同样的需求,可以按照这样的方式处理。。也期待作者下个版本上能支持吧!

直接看代码修改吧
` private int[] mGridSize = new int[2]; // 宫格大小,即图片大小,表示宽高值
private float mRatio = 1.0f; //图片宽高比例,默认1:1.为正方形

@OverRide
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
......
if (mImgDataList.size() == 1 && mSingleImgSize != -1) {
mGridSize[0] = mSingleImgSize > totalWidth ? totalWidth : mSingleImgSize;
mGridSize[1] = calculateRatio(mGridSize[0]);
} else {
mImageViewList.get(0).setScaleType(ImageView.ScaleType.CENTER_CROP);
mGridSize[0] = (totalWidth - mGap * (mColumnCount - 1)) / mColumnCount;
mGridSize[1] = calculateRatio(mGridSize[0]);
}
.......
}

/**
根据比例,通过宽的值,计算高
**/
private int calculateRatio(int width) {
return (int) (width * mRatio);
}

/***
设置宽高比例,如宽高3/4。则传入0.75f即可
*/
public void setImageSizeRatio(float ratio) {
this.mRatio = ratio;
}

//然后修改每一个用到宽高的地方代码,如下:
private void layoutForNoSpanChildrenView(int childrenCount) {
if (childrenCount <= 0) return;
int row, column, left, top, right, bottom;
for (int i = 0; i < childrenCount; i++) {
ImageView childrenView = (ImageView) getChildAt(i);
row = i / mColumnCount;
column = i % mColumnCount;
left = (mGridSize[0] + mGap) * column + getPaddingLeft();//用到宽的地方值
top = (mGridSize[1] + mGap) * row + getPaddingTop();//用到高的地方值
right = left + mGridSize[0];//用到宽的地方值
bottom = top + mGridSize[1];//用到高的地方值
childrenView.layout(left, top, right, bottom);
if (mAdapter != null) {
mAdapter.onDisplayImage(getContext(), childrenView, mImgDataList.get(i));
}
}
}
`

说明:源码中是以前是用mGridSize表示图片宽和高的,现在宽高不一样,用一个数组表示。即可。。

目前已经在源码上修改实现了功能。期待作者下版本能加上此功能。。

开源是伟大的。。希望大家都能贡献一点力量。。。

使用Glide4.0有些图片无法显示

Glide最新的4.0 apply(baseOptions)后很多图片不能加载出来,不设置则没有问题,具体代码如下。
public class PostViewHolder extends RecyclerView.ViewHolder {
private NineGridImageView mNglContent;
private TextView mTvContent;
private RequestOptions baseOptions;

    private NineGridImageViewAdapter<String> mAdapter = new NineGridImageViewAdapter<String>() {

        @Override
        protected void onDisplayImage(Context context, ImageView imageView, String s) {

            Glide.with(context).load(s).apply(baseOptions).into(imageView);

// Picasso.with(context).load(s).placeholder(R.drawable.ic_default_image).into(imageView);
}

        @Override
        protected ImageView generateImageView(Context context) {
            return super.generateImageView(context);
        }

        @Override
        protected void onItemImageClick(Context context, ImageView imageView, int index, List<String> list) {
            Toast.makeText(context, "image position is " + index, Toast.LENGTH_SHORT).show();
        }
    };

    public PostViewHolder(View itemView) {
        super(itemView);
        baseOptions = new RequestOptions()
                .dontAnimate()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .centerCrop()
                .circleCrop()
                .placeholder(R.drawable.ic_default_image)
                .error(R.drawable.ic_default_image);
        mTvContent = (TextView) itemView.findViewById(R.id.tv_content);
        mNglContent = (NineGridImageView<String>) itemView.findViewById(R.id.ngl_images);
        mNglContent.setAdapter(mAdapter);
        mNglContent.setItemImageClickListener(new ItemImageClickListener<String>() {
            @Override
            public void onItemImageClick(Context context, ImageView imageView, int index, List<String> list) {
                Log.d("onItemImageClick", list.get(index));
            }
        });
    }

    public void bind(Post post) {
        mNglContent.setImagesData(post.getImgUrlList(), post.getmSpanType());
        mTvContent.setText(post.getContent());

        Log.d("jaeger", "九宫格高度: " + mNglContent.getMeasuredHeight());
        Log.d("jaeger", "item 高度: " + itemView.getMeasuredHeight());
    }
}

NineGridImageView一个建议

NineGridImageView类中setImagesData(List lists)方法中mImgDataList = lists;这样导致mImgDataList 与传入的参数的内存地址一致,会使oldShowCount与newShowCount的判断永远相等,使第二次调用setImagesData(List lists)报错崩溃。
应该将mImgDataList = lists;修改为mImgDataList = new ArrayList<>(lists);,这样保证了原本作者的意图。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.