`
lovelease
  • 浏览: 386012 次
社区版块
存档分类
最新评论

ViewPager刷新单个页面的方法

阅读更多
  使用ViewPager做滑动切换图片的效果时,如果图片是从网络下载的,那么在子线程中下载完图片时我们会使用handler通知UI线程,然后UI线程就可以调用mViewPager.getAdapter().notifyDataSetChanged()进行页面的刷新,但是viewpager不同于listview,你会发现单纯的调用notifyDataSetChanged()并不能刷新页面。先说说Viewpager的刷新过程:在每次调用notifyDataSetChanged()时,都会激活getItemPosition(Object object)方法,该方法会遍历viewpager的所有item(据我debug的结果,只有当前页和其左右加起来共3页被遍历了,待确定),为每个item返回一个状态值(POSITION_NONE/POSITION_UNCHANGED),如果是none,那么该item会被destroyItem(ViewGroup container, int position, Object object)方法remove掉,然后重新加载,如果是unchanged,就不会重新加载,默认是unchanged,所以如果我们不重写getItemPosition(Object object),就无法看到刷新效果。解决方法有两种:
  第一种网上比较容易查找到:重写PagerAdapter的getItemPosition(Object object)方法,使其返回POSITION_NONE
@Override
public int getItemPosition(Object object) {
	return POSITION_NONE;
}

  这种方法的弊端大家都很容易看出来,我不需要刷新的项目也被重新加载了,浪费系统资源;
  第二种更合理,当然相对前一种要再多做点事:思路是在instantiateItem时给每个view加上tag,然后在需要刷新页面时通过View.getTag()来判断是否是我们想要刷新的页面,只给当前页面返回POSITION_NONE。
/**
 * DispImgAdapter.java
 */
@Override
	public Object instantiateItem(ViewGroup container, int position) {
		iv = new ImageView(mContext);
		iv.setTag(position); // Add tag
        try {
        	Bitmap bm = cacheImg2(position);
            iv.setImageBitmap(bm);
        } catch (OutOfMemoryError e) {
            e.printStackTrace();  
        }
        ((ViewPager)container).addView(iv);
        return iv;
	}

@Override
	public int getItemPosition(Object object) {
		View view = (View)object;
		int currentPage = ((DispImgActivity)mContext).getCurrentPagerIdx(); // Get current page index
        if(currentPage == (Integer)view.getTag()){
            return POSITION_NONE;
        }else{
            return POSITION_UNCHANGED;  
        }
//		return POSITION_NONE;
	}

  关键的currentPageIdx则需要在Activity中获取,如果你的Adapter是Activity的内部类,那么只要把index写成全局变量就可以在adapter中使用了,如果是单独的两个类,那么你就自己提供一个接口,将index传给Adapter便是。
/**
 * DispImgActivity.java
 */
// Get current page index
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
			@Override
			public void onPageScrolled(int i, float f, int j) {
				
			}

			@Override
			public void onPageSelected(int position) {
				DispImgActivity.this.position = position;
			}

			@Override
			public void onPageScrollStateChanged(int i) {
				
			}
		});
// Return current index to Adapter
public int getCurrentPagerIdx() {
		return position;
}


PS:我的项目中还加入了图片下载进度条的功能,当我用第二种方法时,在一些比较极端的情况下会有一点问题,假设所有图片都需要从网上下载,在极快速滑动页面时,发现偶尔会出现异步下载到的图片并没有被刷新显示,在滑过几页重新回到该页时图片才被刷新了,这里涉及到的关键问题是【ViewPager的预加载机制+图片异步下载+getItemPosition中对Tag的判断】,我认为是这几种机制结合后再快速切换页面时造成的问题,由于项目工期的限制,没有去探索更完美的解决方法,反正图片也不是很多,我就采用了第一种方法来做,可以完美的实现我的功能。
分享到:
评论
1 楼 qq_19471875 2016-06-21  
为了感谢楼主 我特意注册了一个账号!,谢谢!很实用!真棒

相关推荐

    Android 使用ViewPager实现view轮播效果,单个item分页样式,多个item分页样式,横向listview

    1. 在PagerAdapter中,确保正确地更新数据并调用`notifyDataSetChanged()`通知ViewPager刷新。 2. 如果使用Fragment,注意处理Fragment的生命周期,避免内存泄漏。 3. 对于横向ListView,可能需要自定义滑动监听器,...

    viewpager+fragment 动态更新数据

    3. 刷新ViewPager:如果数据源的变化需要整个`ViewPager`重新加载,可以调用`ViewPager`的`notifyDataSetChanged`方法。但这种方法可能会导致性能问题,因为它会重新创建所有的`Fragment`。 ```java adapter....

    继承自ViewPager的支持多页显示GridView的自定义控件代码

    然而,单纯的ViewPager通常只能展示单个View或者Fragment,如果我们想要在一个页面中展示像GridView这样的网格布局,就需要进行自定义。本篇文章将探讨如何通过继承ViewPager来实现一个支持多页显示的GridView自定义...

    Fragment和ViewPager组合实现微信模仿

    `Fragment`允许开发者在单个活动中包含多个可交互的UI片段,而`ViewPager`则提供了一个方便的机制,使得用户可以通过左右滑动来浏览这些`Fragment`。 **Fragment** 是Android SDK中的一个类,它代表了屏幕上的一个...

    ViewPager左右滑动月历

    在监听器中,当页面改变时,我们可以更新`Calendar`对象的月份,然后通知`PagerAdapter`数据已改变,通过`notifyDataSetChanged()`刷新`ViewPager`。 在`CalendarDemo`项目中,可能会包含以下关键组件和逻辑: 1. ...

    Android高级应用源码-viewpager+Fragment.rar

    `ViewPager`通常用于创建一个可以左右滑动查看多个页面的视图,而`Fragment`则允许你在单个活动中展示多个可独立管理的UI部分。下面将详细介绍这两个关键概念以及它们如何协同工作。 `ViewPager`是Android Support ...

    ViewPagerTabDemo.zip

    每个页面通常对应一个 `Fragment` 或 `View`,这样可以在单个屏幕空间内展示丰富的交互内容。`ViewPager` 自带平滑滚动效果,提供了一种优雅的方式来处理多页面的展示。 `Fragment` 是Android应用设计中的一个重要...

    Android应用源码模仿zaker风景页面滑动效果修改版源码.zip

    `ViewPager`通常用于实现卡片式的页面切换效果,而`ScrollView`和`HorizontalScrollView`则可以实现单个视图的滚动。 2. **自定义ViewGroup**:为了实现更复杂的效果,开发者可能需要自定义`ViewGroup`,覆盖`...

    fragment实现Tab功能

    在Android应用开发中,Fragment是Android SDK提供的一种组件,它允许开发者在单个活动中展示多个视图或功能。"fragment实现Tab功能"是指利用Fragment来创建类似微信底部导航栏的效果,这种效果通常由多个Tab(标签)...

    TopTab之01

    - 在运行时动态增加或减少Tab,需要更新TabLayout和ViewPager的数据源并调用相应的刷新方法。 7. **动画效果**: - 添加平滑的切换动画可以提升用户体验,如使用`ObjectAnimator`或`Transition`实现过渡效果。 8...

    侧滑+faragment

    ViewPager允许用户通过水平滑动手势在多个Fragment之间切换,实现类似页面翻转的效果。每个Fragment代表一个单独的视图或内容区域,用户可以在不离开当前Activity的情况下浏览多个屏幕。SwipeRefreshLayout则提供了...

    仿微信底部导航菜单

    Fragment允许在单个活动中展示多个界面,而ViewPager则可以用来实现左右滑动切换不同页面的效果。以下是一些关键步骤: 1. **布局设计**:在XML布局文件中,创建一个包含多个ImageView或自定义View(如Bottom...

    网络图片查看器

    刷新功能是网络图片查看器的基本组成部分,它允许用户更新当前显示的图片列表或单个图片。这通常通过下拉刷新手势实现,更新网络数据源,然后重新加载新的或更新的图片。在Android开发中,可以使用...

    ScrollView+双Listview

    `HorizontalScrollView`允许用户水平滑动查看内容,而`ViewPager`则是一个更高级的组件,通常用于实现页面间的平滑切换,常用于展示图片轮播或页面导航。 7. **适配器与数据绑定**: 在`ListView`中,数据通过适配器...

    android 无隐藏BUG v4包

    2. **ViewPager**: ViewPager是Android Support Library v4中的一个强大组件,用于实现滑动切换页面的效果,常用于实现类似Tab或轮播图的功能。它可以承载多个Fragment或者View,并自动处理页面间的滑动过渡,为用户...

    安卓界面之仿浏览器界面

    你可以使用`TabLayout`配合`ViewPager`来实现这个功能,`TabLayout`用于展示标签,`ViewPager`则用于滑动切换不同的页面。 3. **网页内容显示区**:这部分通常由`WebView`组件负责,它允许你在应用程序中加载并显示...

    android-support-v4-src.jar

    6. **View**扩展:`support-v4`库还包含了一些对原生`View`类的扩展,如`SwipeRefreshLayout`(刷新布局)和`ViewPager`(页面滑动查看器)。这些扩展提供了更丰富的用户交互体验,源码中包含了它们的实现逻辑和...

    androidsupportv4.zip

    1. **Widget**: 提供了多种自定义控件,如SwipeRefreshLayout(滑动刷新布局)、ViewPager(页面滑动视图)等,这些控件在原生API级别较低的版本中是不存在的。 2. **View**: 包含了诸如Fragment(碎片)和...

    三,android编码规范 & 常用布局 & 常用控件

    10. **ViewPager**:视图 pager,用于实现页面滑动效果,常用于创建滑动Tab布局。 理解并熟练运用这些布局和控件,将极大地提升Android应用的开发效率和用户体验。同时,遵循编码规范可以使代码更易读,便于团队...

    android平台特色控件

    NestedScrollView是支持嵌套滚动的布局,它允许在单个视图内包含其他可滚动的视图,如ScrollView或HorizontalScrollView,特别适合在内容较多且需要滚动的场景。 10. **BottomNavigationView(底部导航栏)** ...

Global site tag (gtag.js) - Google Analytics