Android应用中使用ViewPager实现类似QQ的界面切换效果

 更新时间:2016年03月23日 10:50:11   作者:vampirecarter  
这篇文章主要介绍了Android应用中使用ViewPager实现类似QQ的界面切换效果的示例,文中的例子重写了PagerAdapter,并且讲解了如何解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题,需要的朋友可以参考下

这几天在研究ViewPager,简单的写一下如何使用ViewPager实现类似于QQ的“最近联系人、好友、群组”的界面切换(不知道他们是不是用这个方法实现的)。
ViewPager已经在android-sdk中加入了,具体的位置在%android_sdk_home%\android-compatibility\v4,%android_sdk_home%是你的android-sdk-windows目录。

好,下面放一张效果图:

2016323104647071.png (480×800)

步骤一:新建一个工程,我的是Viewpager
步骤二:导入jar包
具体如下:
右键工程--Properties--单击左侧Java Build Path--单击右侧Libraries标签--单击右侧Add External Jars--选择上面描述位置的jar包,保存

步骤三:编写一个主界面,加入android.support.v4.view.ViewPager组件

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:orientation="vertical" > 
 
  <TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello" /> 
   
   
  <android.support.v4.view.ViewPager 
    android:id="@+id/mViewPager" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    /> 
 
   
</LinearLayout> 

步骤四:编写三个要添加进来的界面
界面都很简单,随便写的
界面1

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:background="#ff0000" 
  android:orientation="vertical" > 
 
  <Button 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="layout1" /> 
 
</LinearLayout> 

界面2

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:background="#00ff00" 
  android:orientation="vertical" > 
 
  <TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="layout2" /> 
 
</LinearLayout>

 

界面3

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent" 
  android:background="#0000ff" 
  android:orientation="vertical" > 
 
  <TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="layout3" /> 
 
</LinearLayout> 

步骤五:编写主类,我的名字是叫ViewpagerActivity

package com.carter.viewpager; 
 
import java.util.ArrayList; 
import java.util.List; 
import java.util.zip.Inflater; 
 
import android.app.Activity; 
import android.app.ActivityGroup; 
import android.content.Intent; 
import android.os.Bundle; 
import android.support.v4.view.PagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.support.v4.view.ViewPager.OnPageChangeListener; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
 
public class ViewpagerActivity extends ActivityGroup { 
   
  /** 
   * 能够支持滑动的组件 
   */ 
  ViewPager mViewPager; 
   
  /** 
   * ViewPager 需要设置该Adapter才能实现添加界面, 
   * 该Adapter继承自PagerAdapter 
   */ 
  MyPagerAdapter adapter; 
   
  /** 
   * 用于保存三个界面 
   */ 
  List<View> list;  
   
  /** 
   * 用于生成界面 
   */ 
  LayoutInflater mInflater; 
   
   
   
   
  /** Called when the activity is first created. */ 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
     
    mInflater = this.getLayoutInflater(); 
     
    /** 
     * 添加进来三个界面到List,用于初始化PagerAdapter 
     */ 
    list = new ArrayList<View>(); 
    list.add(this.getLocalActivityManager().startActivity("layout1", new Intent(ViewpagerActivity.this, Layout1Activity.class)).getDecorView()); 
    list.add(mInflater.inflate(R.layout.layout2, null)); 
    list.add(mInflater.inflate(R.layout.layout3, null)); 
     
    mViewPager = (ViewPager)findViewById(R.id.mViewPager); 
    adapter = new MyPagerAdapter(list); 
    mViewPager.setAdapter(adapter); 
     
    /** 
     * 为ViewPager添加PageChangeListener,在回调的方法中可以完成其他的事情,例如处理一些界面标签的转换之类的,如果你有标签栏的话 
     */ 
    mViewPager.setOnPageChangeListener(new OnPageChangeListener() { 
       
      @Override 
      public void onPageSelected(int arg0) { 
        // TODO Auto-generated method stub 
        Log.i("carter", "onPageSelected"); 
      } 
       
      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) { 
        // TODO Auto-generated method stub 
         
      } 
       
      @Override 
      public void onPageScrollStateChanged(int arg0) { 
        // TODO Auto-generated method stub 
         
      } 
    }); 
     
  } 
   
   
   
   
  class MyPagerAdapter extends PagerAdapter 
  { 
    List<View> mList; 
     
    public MyPagerAdapter(List<View> list){ 
      mList = list; 
    } 
 
    @Override 
    public int getCount() { 
      // TODO Auto-generated method stub 
      return mList.size(); 
    } 
 
    @Override 
    public boolean isViewFromObject(View arg0, Object arg1) { 
      // TODO Auto-generated method stub 
      return arg0 == (arg1); 
    } 
 
    @Override 
    public void destroyItem(View container, int position, Object object) { 
      // TODO Auto-generated method stub 
      ((ViewPager)container).removeView(mList.get(position)); 
    } 
 
    @Override 
    public Object instantiateItem(View container, int position) { 
      // TODO Auto-generated method stub 
      ((ViewPager)container).addView(mList.get(position), 0); 
      return mList.get(position); 
    }     
 
    @Override 
    public void finishUpdate(ViewGroup container) { 
      // TODO Auto-generated method stub 
      super.finishUpdate(container); 
    } 
  } 
} 

代码解读:
1、在上面重写了PagerAdapter,在里面最重要的方法就是

@Override 
    public Object instantiateItem(View container, int position) { 
      // TODO Auto-generated method stub 
      ((ViewPager)container).addView(mList.get(position), 0); 
      return mList.get(position); 
    }  

具体为什么每次都是addView到0的位置,目前我还不知道,这个也是从网上找了一个方法看到的。

2、在初始化List的时候,里面包含的内容是一个个的View元素,在我的了解范围内有两种方法
第一种就是通过添加Window的getDecorView()来得到一个View;
第二种就是通过LayoutInflater,从xml中生成一个View。
需要注意的是,第一种方法,需要主类继承自ActivityGroup,这样才能在添加时使用getLocalActivityManager以及之后的方法,需要生成的Activity,例如本例中的Layout1Activity,要在AndroidManifest.xml中声明。

/** 
 * 添加进来三个界面到List,用于初始化PagerAdapter 
 */ 
list = new ArrayList<View>(); 
list.add(this.getLocalActivityManager().startActivity("layout1", new Intent(ViewpagerActivity.this, Layout1Activity.class)).getDecorView()); 
list.add(mInflater.inflate(R.layout.layout2, null)); 
list.add(mInflater.inflate(R.layout.layout3, null)); 

3、如果只是从xml生成View来添加的话,完全可以移除继承ActivityGroup。
4、如果使用startActivity的方法来启动,需要添加进来的几个Activity,是一起在加入时就初始化的,可以通过在onCreate()方法中打LOG看出来。

PS:如何解决Android下ViewPager和PagerAdapter中调用notifyDataSetChanged失效的问题
具体讲解如下:
Google在Android 3.0SDK中推出的ViewPager控件很大程度上满足了开发者开发页面左右移动切换的功能,使用非常方便。但是使用中发现,在删除或者修改数据的时候,PagerAdapter无法像BaseAdapter那样仅通过notifyDataSetChanged方法通知刷新View。
最基本的方法:
针对于child view比较简单的情况(例如仅有TextView、ImageView等,没有ListView等展示数据的情况),可以在自己的Adapter中加入代码:

@Override  
public int getItemPosition(Object object) {  
  return POSITION_NONE;  
}  

这样既可达到一般情况下要求的效果。
存在的问题:
这不是PagerAdapter中的Bug,通常情况下,调用notifyDataSetChanged方法会让ViewPager通过Adapter的getItemPosition方法查询一遍所有child view,这种情况下,所有child view位置均为POSITION_NONE,表示所有的child view都不存在,ViewPager会调用destroyItem方法销毁,并且重新生成,加大系统开销,并在一些复杂情况下导致逻辑问题。特别是对于只是希望更新child view内容的时候,造成了完全不必要的开销。
更有效地方法:
更为靠谱的方法是因地制宜,根据自己的需求来实现notifyDataSetChanged的功能,比如,在仅需要对某个View内容进行更新时,在instantiateItem()时,用View.setTag方法加入标志,在需要更新信息时,通过findViewWithTag的方法找到对应的View进行更新即可。

相关文章

  • Android中如何使用Glide加载图像

    Android中如何使用Glide加载图像

    大家好,本篇文章主要讲的是Android中如何使用Glide加载图像,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Flutter自定义Appbar搜索框效果

    Flutter自定义Appbar搜索框效果

    这篇文章主要为大家详细介绍了Flutter自定义Appbar搜索框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Android实现扫雷小游戏

    Android实现扫雷小游戏

    这篇文章主要为大家详细介绍了Android实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Flutter使用Overlay与ColorFiltered新手引导实现示例

    Flutter使用Overlay与ColorFiltered新手引导实现示例

    这篇文章主要介绍了Flutter使用Overlay与ColorFiltered新手引导实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Android之Gallery使用例子

    Android之Gallery使用例子

    本篇文章主要介绍了Android之Gallery使用例子,Gallery用来显示图片列表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Android编程之selector下设置背景属性值的方法

    Android编程之selector下设置背景属性值的方法

    这篇文章主要介绍了Android编程之selector下设置背景属性值的方法,结合实例形式分析了Android的selector背景选择器相关使用技巧,需要的朋友可以参考下
    2016-01-01
  • Android实现九宫格解锁

    Android实现九宫格解锁

    根据最近Android项目需要,实现九宫格解锁效果,下面小编给大家分享了具体实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • Android ScrollView嵌套ExpandableListView显示不正常的问题的解决办法

    Android ScrollView嵌套ExpandableListView显示不正常的问题的解决办法

    这篇文章主要介绍了Android ScrollView嵌套ExpandableListView显示不正常的问题的解决办法的相关资料,需要的朋友可以参考下
    2017-02-02
  • UI 开源组件Flutter图表范围选择器使用详解

    UI 开源组件Flutter图表范围选择器使用详解

    这篇文章主要为大家介绍了UI 开源组件Flutter图表范围选择器使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Android 短信验证码自动填写

    Android 短信验证码自动填写

    这篇文章主要介绍了Android 短信验证码自动填写的相关资料,需要的朋友可以参考下
    2017-06-06

最新评论