photo player 显示 ☞ 列表选中项的处理
photo player 显示☞列表选中项的处理
一、需求
- 需要显示一个图片列表,可以左右滑动,点击则在大图显示该图;
- 可以在界面上显示大图,可以左右滑动切换图片,可以支持zoom、move、rotate;
- 大图与图片列表相互关联:
- 点击列表item可以在show对应大图;
- 大图切换则列表保持该Item在列表中间位置;
- 对于大图显示的图片添加红框标记(item的两个背景);
效果如此图:
二、当前方案
- 大图显示使用ViewPager控件实现,则可以支持左右滑动切换图片功能(支持预加载);
- 图片列表使用RecyclerView控件来实现,则可以支持列表功能,同时其缓存机制对于机器更加友好;
- 列表关联功能可以自行实现:
- 点击item show对应大图:对每个item添加点击事件监听,点击则设置viewpager显示指定position图片;
- 添加对于ViewPager的滑动监听,添加对于列表移动的处理;
- 显示的图片在列表中设置红框标记,这里前后使用两个方案实现:
- 使用arraylist维护对应的标记,在show图片时添加判断,viewpager切换则刷新列表显示;
- 在adapter中维护一个变量,记录当前显示的图片,viewpager切换则刷新列表中背景切换的两个item,且仅处理其背景,并不刷新该item中imageview;
本次记录的重点在于红框标记的两个方案实现,方案2比方案1节省了大量资源:列表、刷新item数量、控件
三、关联具体实现
3.1 方案一:
adapter中维护一个boolean类型的list,大小与imagelist相同,选中设置为true,其余设置为false:
public List<Boolean> isClicks; //控件是否被点击,默认为false,如果被点击,改变值,控件根据值改变自身颜色 isClicks = new ArrayList<>(); for (int i = 0; i < mImageList.size(); i++) {isClicks.add(false); }
在init list item view的时候,判断上述值:
@Override public void onBindViewHolder(final ViewHolder holder, int position) {...if (isClicks.get(position)) {imageItem.setBackgroundResource(R.drawable.photo_preview__btn_p);} else {imageItem.setBackgroundResource(R.drawable.photo_preview__btn_n);}... }
ViewPager滑动的时候改变对应的值,并更新:
private NoPreloadViewPager.OnPageChangeListener mPhotoPageChangeListener = new NoPreloadViewPager.OnPageChangeListener() {@Overridepublic void onPageSelected(int position) {mPosition = position;mRecycleAdapter.isClicks.set(mPosition, true);for(int i = 0; i <mRecycleAdapter.isClicks.size();i++){mRecycleAdapter.isClicks.set(i,false);}mRecycleAdapter.isClicks.set(position,true);//此接口会将所有可见的item重新刷新一遍mRecycleAdapter.notifyDataSetChanged();MoveToPosition(mLayoutManager, mPhotoListView, position);}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {//arg0 ==1的时表示正在滑动,arg0==2的时表示滑动完毕了,arg0==0的时表示什么都没做。if (arg0 == 0) {} else if (arg0 == 1) {} else if (arg0 == 2) {}} };//根据当前view切换将要显示的item移动到中间位置 public void MoveToPosition(LinearLayoutManager manager, RecyclerView recyclerView, int position) {int firstItem = manager.findFirstVisibleItemPosition();int lastItem = manager.findLastVisibleItemPosition();int offset = (lastItem - firstItem) / 2;int maxItem = mPhotoList.size() - 1;int center = (lastItem + firstItem) / 2;int offsetPosition = 0;if (position < center) {offsetPosition = position - offset;} else if (position == center) {offsetPosition = position;} else {offsetPosition = position + offset;}if (offsetPosition < 0) {offsetPosition = 0;} else if (offsetPosition > maxItem) {offsetPosition = maxItem;}recyclerView.scrollToPosition(offsetPosition); }
列表item点击时:
private PhotoListAdapter.Callback mPhotoListItemCallback = new PhotoListAdapter.Callback() {@Overridepublic void onItemClick(Image image, ImageView imageItem) {mPosition = mPhotoList.indexOf(image);//todo set the current item in centermPhotoView.setCurrentItem(mPosition);} };
这里在点击列表item的时候并没有做notify item列表的处理:1. 这里两个控件要避免操作成环;
2. ViewPager控件中的setCurrentItem接口,在其内部实现中会调用到:mOnPageChangeListener.onPageSelected(item);/*** Set the currently selected page. If the ViewPager has already been through its first* layout there will be a smooth animated transition between the current item and the* specified item.* @param item Item index to select*/ public void setCurrentItem(int item) {mPopulatePending = false;setCurrentItemInternal(item, !mFirstLayout, false); }/*** Set the currently selected page.* @param item Item index to select* @param smoothScroll True to smoothly scroll to the new item, false to transition immediately*/ public void setCurrentItem(int item, boolean smoothScroll) {mPopulatePending = false;setCurrentItemInternal(item, smoothScroll, false); } void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {setCurrentItemInternal(item, smoothScroll, always, 0); }void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {if (mAdapter == null || mAdapter.getCount() <= 0) {setScrollingCacheEnabled(false);return;}if (!always && mCurItem == item && mItems.size() != 0) {setScrollingCacheEnabled(false);return;}if (item < 0) {item = 0;} else if (item >= mAdapter.getCount()) {item = mAdapter.getCount() - 1;}final int pageLimit = mOffscreenPageLimit;if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {// We are doing a jump by more than one page. To avoid// glitches, we want to keep all current pages in the view// until the scroll ends.for (int i=0; i<mItems.size(); i++) {mItems.get(i).scrolling = true;}}final boolean dispatchSelected = mCurItem != item;mCurItem = item;populate();final int destX = (getWidth() + mPageMargin) * item;if (smoothScroll) {smoothScrollTo(destX, 0, velocity);if (dispatchSelected && mOnPageChangeListener != null) {mOnPageChangeListener.onPageSelected(item);}} else {if (dispatchSelected && mOnPageChangeListener != null) {mOnPageChangeListener.onPageSelected(item);}completeScroll();scrollTo(destX, 0);} }
所以这里按照上述方式实现:
- 维护一个list;
- 每次更新都在重新设置一遍list;
- notify 数据变化时,当前可见的item都要刷新一遍;
3.2 方案二:
基于上述方案进行优化:
- 由于每次选中的图片仅一个,则可以使用一个变量来维护;
- 每次在view切换的时候,现在是更新整个list,而这里可以仅设置一个值;
- 每次在view切换之后需要通知列表更新数据,现在是更新所有可见列表,这里可以仅更新两个item;
- 每次更新view的时候,都是将这个view完整的重新加载,这里可以仅更新item的背景图,而不去重新加载图片;
则具体来看code实现:
使用变量来标记当前显示的图片:
//M: add select solution private int selectPosition = -1; public void setSelectPosition(int position) {if (0 > position ||mImageList.size() < position ){Debug.i(TAG, "position error: " + position);return;}selectPosition = position; } public int getSelectPosition( ) {return selectPosition; }
获取此前一次显示的位置,更新当前显示的位置,并通知adapter有数据变化::
//add viewpager item click listener private NoPreloadViewPager.OnPageChangeListener mPhotoPageChangeListener = new NoPreloadViewPager.OnPageChangeListener() {int oldPosition = 0;@Overridepublic void onPageSelected(int position) {mPosition = position;//获取前一个显示的position,并设置当前显示的position;oldPosition = mRecycleAdapter.getSelectPosition();mRecycleAdapter.setSelectPosition(position);//注意,这里更新使用notifyItemChanged,仅更新上述两个位置的item//第二个参数为0表示payloads不为空,是只更新item某一个控件,而不是完整更新的关键mRecycleAdapter.notifyItemChanged(oldPosition, 0);mRecycleAdapter.notifyItemChanged(position, 0);//照例让RecyclerView滑动到指定位置MoveToPosition(mLayoutManager, mPhotoListView, position);}@Overridepublic void onPageScrolled(int position, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {//arg0 ==1的时表示正在滑动,arg0==2的时表示滑动完毕了,arg0==0的时表示什么都没做。if (arg0 == 0) {} else if (arg0 == 1) {} else if (arg0 == 2) {}} };
adapter中处理仅更新item的背景图:
@Override public void onBindViewHolder(final ViewHolder holder, int position) { }//此函数不去实现,转而实现下述带payloads参数的接口@Override public void onBindViewHolder(final ViewHolder holder, final int position, List payloads) {final Image image = mImageList.get(position);final ImageView imageItem = holder.imageItem;final ProgressBar loading = holder.loading;final String imagePath = image.getImagePath();if(payloads.isEmpty()) {//这里是关键:正常刷新时走这里,主要是load图片和添加click监听imageItem.setImageDrawable(mContext.getDrawable(R.drawable.photo_preview__btn_n));loading.setVisibility(View.VISIBLE);holder.imageItem.setTag(imagePath);mImageLoader.loadImage(holder.imageItem,imagePath,true,position,new ImageLoader.onImageLoadedListener() {@Overridepublic void displayImage(ImageView view, Bitmap bitmap) {//check if there is the correct viewString path = view.getTag().toString();if (path.equals(imagePath)) {view.setImageBitmap(bitmap);loading.setVisibility(View.GONE);}}});if (mCallback != null) {holder.imageItem.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mCallback.onItemClick(position, imageItem);}});}} else {//选中图片背景图更新时走这里,只判断position更新背景图//set background resource//init or select all need set the background rescource, so move it // to this function out}if (position == selectPosition) {imageItem.setBackgroundResource(R.drawable.photo_preview__btn_p);} else {imageItem.setBackgroundResource(R.drawable.photo_preview__btn_n);} }
整体来讲改动比较小,但是加载图片时对于资源的消耗要降低了很多
photo player 显示 ☞ 列表选中项的处理相关推荐
- Flash Player渲染模型(显示列表)
显示列表是Flash Player 9以后才有的Flash渲染模型,这是一个非常重要的模型.那么为什么要彻底改变Flash对图形的操作方式呢?原因有两个:速度和简化.以前显示列表各个方面都是Movie ...
- ListBox选中项数量显示于TextBox文本框中
要完成的功能:点击ListBox选中一个或多个选项时,TextBox中自动显示选中项的数量. 如下图显示: 分析: 你原先错误的思路:ListBox配置好数据源,然后在TextBox的后台事件Text ...
- ASP.NET MVC中为DropDownListFor设置选中项的方法
在MVC中,当涉及到强类型编辑页,如果有select元素,需要根据当前Model的某个属性值,让Select的某项选中.本篇只整理思路,不涉及完整代码. □ 思路 往前台视图传的类型是List< ...
- vue 中使用element-ui的menu选中项高亮的问题
在使用element中的menu组件时,根据官方文档,可以设置给el-menu设置router属性为:true,给el-menu-item设置index的值为路径,就可以实现点击导航跳转到指定路由. ...
- Android ListView选中项居中放大(使用上下键控制,非触屏)
最近有一个功能机项目(不支持触屏)需要实现ListView选中项停在中间放大的效果,网络上的大多是用手滑动屏幕的效果,只能自己写一个. 效果实现了,但是还有小问题.实现原理主要是 1调用setSele ...
- sharepoint中显示网页库item的webpart和显示列表库item的webpart
首先是在任意位置显示网页库中网页的ITEM的webpart 公司动态和公司公告列表Page在只显示Title的情况先查询出来的栏 Title _ModerationStatus(审批状态) ID Fi ...
- Qt5 QML TreeView currentIndex当前选中项的一些问题
0.前言 Qt5 QML Controls1.4 中的 TreeView 存在诸多问题,比如节点连接的虚线不好实现,currentIndex 的设置和 changed 信号的触发等.我想主要的原因在于 ...
- Vue中select下拉框的默认选中项的三种情况
在Vue中 使用select下拉框 主要靠的是 v-model 来绑定选项 option 的 value 值. select下拉框在界面的展示,我们都希望看到框中有一个值 而不是空白,比如显示 &qu ...
- 关于select2 默认选中 动态选中 显示,刷新选中等操作
关于select2设置不了 显示 却能设置 因为项目原因 用到了select2 而我一小白用传统select去设置 然后百度 gogle摸索来摸索去弄了2天,最后还是找到了 为了方便查找以后总结一下 ...
- as3学习第二课 显示对象和显示列表
关于显示对象 原文地址:as3学习第二课 显示对象和显示列表 作者:冰剑蓝影 一.显示对象 显示对象就是可以在舞台上显示的对象.包括直接看到的对象,如图形.文字.图片.视频.还有看不到但又真 ...
最新文章
- java线程触发_java线程
- zen3架构_AMD Zen3架构处理器的L3缓存或将翻倍到64MB
- GitHub开源:狗屁不通文章生成器
- linux 读书笔记
- (2.10)备份与还原--利用T-SQL进行备份还原
- centos 安装testlink出现:You don't have permission to access /testlink on this server
- Light Head R-CNN论文笔记
- 【转】c# [Serializable]的作用
- 理请求时出现未知错误.服务器返回的状态码为: 500,react-native
- php100教程源码,PHP100 视频教程 2012-2013版_PHP教程
- 容器编排技术 -- Kubernetes kubectl create secret tls 命令详解
- 条款01:视C++为一个语言联邦
- 如何自定义Struts2表单验证后的错误信息显示格式
- factory工厂模式之工厂方法FactoryMethod
- aptana手动配置python环境_Python学习1:使用Aptana构建Python开发环境
- 【父亲节H5】用独特的方式表达最深沉的爱!
- Solidworks二次开发平台 --- RyS.SwWorks [2015-09-18更新]
- Oracle同英超联赛数据统计和展示的结合
- dlna 交互步骤-转发
- Strange Fractions(奇怪的分数)-数论