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

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

好,下面放一张效果图:

步骤一:新建一个工程,我的是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进行更新即可。

(0)

相关推荐

  • Android中TabLayout结合ViewPager实现页面切换效果

    先看看效果,如图: 1.因为TabLayout是Android Design Support Library官方库的一个控件,所以使用TabLayout时候需要先添加对该库的依赖 compile 'com.android.support:design:22.2.0' 2.下面是TabLayout和ViewPager配合使用的布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns

  • Android中ViewPager组件的基本用法及实现图片切换的示例

    ViewPager是android-support-v4.jar包里的组件.在布局文件里标签需要连包名一起 写全称<android.support.v4.view.ViewPager /> 基本用法 ViewPager的基本用法我概括为三步 第一步 在主布局文件里放一个ViewPager组件 第二步 为每个页面建立布局文件,把界面写好 第三步 在主Activity里获取ViewPager组件,并为它设定Adapter. Adapter详细讲讲,ViewPager对应的Adapter继承自Pag

  • Android实现单页显示3个Item的ViewPager炫酷切换效果

    单页显示3个Item的ViewPager炫酷切换效果,适用于Banner等. 效果图 Rotate Y Rotate Down Rotate Up Alpha ScaleIn ScaleIn + Alpha + Rotate Down 使用 ###(1)引入 compile `com.zhy:magic-viewpager:1.0.1` ###(2)示例 布局文件 <FrameLayout android:layout_width="match_parent" android:l

  • 灵活使用Android中ActionBar和ViewPager切换页面

    本文实例讲述了Android使用ActionBar和ViewPager切换页面,分享给大家供大家参考.具体如下: 运行效果截图如下: 项目布局如下: 具体代码如下: MainActivity.java代码 import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.

  • Android编程实现ViewPager多页面滑动切换及动画效果的方法

    本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

  • Android App中使用ViewPager+Fragment实现滑动切换效果

    在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android-support-v4.jar.细节无法控制.不过现在情况已经不一样了,android-support-v4中提供了很多实用的功能,以至于现在新建一个android工程默认都会导入这个jar包.那我们就也采用viewpager来做滑动吧.另外一个概念就是Fragment和FragmentActivit

  • Android开发之使用ViewPager实现图片左右滑动切换效果

    Android中图片的左右切换随处可见,今天我也试着查阅资料试着做了一下,挺简单的一个小Demo,却也发现了一些问题,话不多说,上代码~: 使用了3个xml文件作为ViewPager的滑动page,布局都是相同的,如下只展示其中之一: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/

  • Android应用中利用ViewPager实现多页面滑动切换效果示例

    1.添加android support包 因为上面的几个类都是在android support包中才提供,我们先添加包. 在Eclipse->Window->Android SDK Manager,选择列表中Extras->Android Support Library进行安装.下载完后在android-sdk\extras\android\support目录下,这里我们选择v4版本,进入v4目录,拷贝其中的android-support-v4.jar文件到工程的libs目录(若没有新建

  • Android ViewPager实现选项卡切换

    本文实例介绍了ViewPager实现选项卡切换,效果图如下: 步骤一:这里使用兼容低版本的v4包进行布局,这里eclipse没有输入提示,所以要手动输入,文件名称"activity_main.xml" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"

  • Android实现千变万化的ViewPager切换动画

    之前写过一篇文章:Android自定义ViewPager实现个性化的图片切换效果,有朋友提出,ViewPager自带了一个setPageTransformer用于设置切换动画~ 本篇文章,将进行以下内容学习: 1.介绍如何使用setPageTransformer设置切换动画: 2.自定义PageTransformer实现个性的切换动画: 3.该方法在SDK11以下的版本不起作用,我们会对其做一定修改,让其向下兼容. 官方示例地址:http://developer.android.com/trai

随机推荐