Android:UI控件ViewPager,notifyDataSetChanged

简介:

ViewPager的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public  class  MainActivity  extends  Activity
{
     /*
      * XML添加viewpager方法:
      *   <android.support.v4.view.ViewPager
      *   android:id="@+id/viewPager"
      *   android:layout_width="match_parent"
      *   android:layout_height="match_parent"/>
      */
                            
                            
     int [] ImageIds =  new  int []
     { R.drawable.guide_daily_brand, R.drawable.guide_item_detail_1, R.drawable.guide_item_detail_2, R.drawable.guide_multi_shop_detail,
             R.drawable.guide_pic_mode, R.drawable.guide_timeline_filter };
                            
     private  ArrayList<View> mViewList =  new  ArrayList<View>();
                            
     @Override
     protected  void  onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
                                
         ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
         viewPager.setAdapter( new  PagerAdapter()
         {
             @Override
             public  Object instantiateItem(View container,  int  position)
             {
                 //第一页和最后一页只创建保留两个view来复用,中间则保留三个view
                 LayoutInflater inflater = getLayoutInflater();
                 View layout = inflater.inflate(R.layout.pager_item,  null );
                                        
                 //将View加入到容器和container里面,不加判断会造成泄漏
                 if (mViewList.size() < ImageIds.length)
                 {
                     mViewList.add(layout);
                 }
                 
                 ((ViewPager) container).addView(layout,  0 );
                                        
                 layout.setBackgroundResource(ImageIds[position]);
                 return  layout;
             }
                                    
             @Override
             public  void  destroyItem(View container,  int  position, Object object)
             {
                 //此处的position与上面的并不相等,会自动销毁不在当前页左右的view
                 ((ViewPager) container).removeView(mViewList.get(position));
             }
                                    
             @Override
             public  boolean  isViewFromObject(View arg0, Object arg1)
             {
                 return  arg0 == arg1; //判断对象与类型
             }
                                    
             @Override
             public  int  getCount()
             {
                 return  ImageIds.length;
             }
         });
                                
     }
                            
     @Override
     public  boolean  onCreateOptionsMenu(Menu menu)
     {
         getMenuInflater().inflate(R.menu.main, menu);
         return  true ;
     }
                            
}




其他笔记:

1.viewpager切换时容易造成oom问题

1
2
3
4
5
6
mViewPager = (ViewPager) findViewById(R.id.photogallery_viewpager);
mAdapter =  new  PhotoGalleryAdapter();
//限制view的数量,减少view缓存,在setAdapter之前使用
mViewPager.setOffscreenPageLimit( 3 );
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mPagerSelected);


2.两种removeview方法

1
2
3
4
5
6
         @Override
         public  void  destroyItem(View container,  int  position, Object object)
         {
//             ((ViewPager) container).removeView((View) object);
             ((ViewPager) container).removeView(mViewList.get(position));
         }


3.关于notifyDataSetChanged()方法无法及时更新的问题解决方法

(1)销毁ViewItem时要使用以下方法:

1
2
3
4
5
6
         @Override
         public  void  destroyItem(View container,  int  position, Object object)
         {
//            ((ViewPager) container).removeView(mViewList.get(position));
              ((ViewPager) container).removeView((View)object);
         }

参考资料:http://www.myexception.cn/android/417891.html


(2)重写notifyDataSetChanged()和getItemPosition(Object object)方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
         private  int  mChildCount =  0 ;
         
         @Override
         public  void  notifyDataSetChanged()
         {
             mChildCount = getCount();
             super .notifyDataSetChanged();
         }
         
         @Override
         public  int  getItemPosition(Object object)
         {
             if  (mChildCount >  0 )
             {
                 mChildCount--;
                 return  POSITION_NONE;
             }
             return  super .getItemPosition(object);
         }


参考资料:http://www.cnblogs.com/maoyu417/p/3740209.html


附相关注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
进入viewpager,我们终于找到了viewpager中控制数据变更的重点方法dataSetChanged ,这个方法如下:
       void  dataSetChanged () {
         // This method only gets called if our observer is attached, so mAdapter is non-null.
  
         boolean  needPopulate = mItems .size() < mOffscreenPageLimit *  2  1  &&
                 mItems.size() < mAdapter.getCount();
         int  newCurrItem = mCurItem ;
  
         boolean  isUpdating =  false ;
         for  ( int  i =  0 ; i < mItems.size(); i++) {
             final  ItemInfo ii = mItems .get(i);
             final  int  newPos = mAdapter.getItemPosition(ii.object );
  
             if  (newPos == PagerAdapter.POSITION_UNCHANGED ) {
                 continue ;
             }
  
             if  (newPos == PagerAdapter.POSITION_NONE) {
                 mItems.remove(i);
                 i--;
  
                 if  (!isUpdating) {
                     mAdapter.startUpdate(  this );
                     isUpdating =  true ;
                 }
  
                 mAdapter.destroyItem(  this , ii.position , ii.object);
                 needPopulate =  true ;
  
                 if  (mCurItem == ii.position ) {
                     // Keep the current item in the valid range
                     newCurrItem = Math. max( 0 , Math.min(mCurItem, mAdapter.getCount() -  1 ));
                     needPopulate =  true ;
                 }
                 continue ;
             }
  
             if  (ii.position != newPos) {
                 if  (ii.position == mCurItem ) {
                     // Our current item changed position. Follow it.
                     newCurrItem = newPos;
                 }
  
                 ii. position = newPos;
                 needPopulate =  true ;
             }
         }
  
         if  (isUpdating) {
             mAdapter.finishUpdate(  this );
         }
  
         Collections. sort(mItems, COMPARATOR);
  
         if  (needPopulate) {
             // Reset our known page widths; populate will recompute them.
             final  int  childCount = getChildCount();
             for  ( int  i =  0 ; i < childCount; i++) {
                 final  View child = getChildAt(i);
                 final  LayoutParams lp = (LayoutParams) child.getLayoutParams();
                 if  (!lp.isDecor ) {
                     lp. widthFactor =  0 .f;
                 }
             }
  
             setCurrentItemInternal(newCurrItem,  false true );
             requestLayout();
         }
     }
  
   重点看这样一行代码:
  final  int  newPos = mAdapter.getItemPosition(ii.object );
  
    if  (newPos == PagerAdapter.POSITION_UNCHANGED ) {
          continue  ;
    }
  
   官方对getItemPosition()的解释是:
   Called when the host view is attempting to determine  if  an item’s position has changed. Returns POSITION_UNCHANGED  if  the position of the given item has not changed orPOSITION_NONE  if  the item is no longer present in the adapter.
The  default  implementation assumes that items will never change position and always returns POSITION_UNCHANGED.
   意思是如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,而返回POSITION_UNCHANGED
  
解决方案:
   所以我们可以尝试着修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。




本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1224648,如需转载请自行联系原作者
目录
相关文章
|
6天前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
14 3
|
23天前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
23天前
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
31 1
|
1月前
|
API Android开发
Android项目架构设计问题之选择和使用合适的UI库如何解决
Android项目架构设计问题之选择和使用合适的UI库如何解决
38 0
|
1月前
|
Android开发
Android使用ViewPager做无限轮播,人为滑动时停止
Android使用ViewPager做无限轮播,人为滑动时停止
22 2
|
1月前
|
C# 开发者 Windows
一款基于Fluent设计风格、现代化的WPF UI控件库
一款基于Fluent设计风格、现代化的WPF UI控件库
|
26天前
|
前端开发 Android开发 开发者
安卓开发中的自定义视图:构建你的第一个控件
【8月更文挑战第26天】在安卓开发的浩瀚海洋中,自定义视图是一块充满魔力的乐土。它不仅是开发者展示创造力的舞台,更是实现独特用户体验的关键。本文将带你步入自定义视图的世界,从基础概念到实战应用,一步步教你如何打造自己的第一个控件。无论你是初学者还是有经验的开发者,这篇文章都将为你的开发之旅增添新的风景。
|
2月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
【7月更文挑战第28天】随着移动应用市场的发展,用户对界面设计的要求不断提高。Material Design是由Google推出的设计语言,强调真实感、统一性和创新性,通过模拟纸张和墨水的物理属性创造沉浸式体验。它注重色彩、排版、图标和布局的一致性,确保跨设备的统一视觉风格。Android Studio提供了丰富的Material Design组件库,如按钮、卡片等,易于使用且美观。
87 1
|
3月前
|
Android开发 开发者
Android UI设计中,Theme定义了Activity的视觉风格,包括颜色、字体、窗口样式等,定义在`styles.xml`。
【6月更文挑战第26天】Android UI设计中,Theme定义了Activity的视觉风格,包括颜色、字体、窗口样式等,定义在`styles.xml`。要更改主题,首先在该文件中创建新主题,如`MyAppTheme`,覆盖所需属性。然后,在`AndroidManifest.xml`中应用主题至应用或特定Activity。运行时切换主题可通过重新设置并重启Activity实现,或使用`setTheme`和`recreate()`方法。这允许开发者定制界面并与品牌指南匹配,或提供多主题选项。
44 6
|
2月前
|
C# Windows
一款开源、免费、现代化风格的WPF UI控件库
一款开源、免费、现代化风格的WPF UI控件库