android视图切换控件,Android中的ViewPager视图滑动切换类的入门实例教程

ViewPager引入示例首先让大家有个全局的认识,直接上个项目,看看仅仅通过这几行代码,竟然就能完成如此强悍的功能。

效果图:

实现了三个view间的相互滑动。

第一个VIEW向第二个VIEW滑动、第二个VIEW向第三个VIEW滑动

62ad8d6c3f4df08691d2facc8e0befb5.png

cd42d8cc639226c3e805ae860fa8b4d7.png

一、新建项目,引入ViewPager控件ViewPager。它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换。

1.在主布局文件里加入

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

tools:context="com.example.testviewpage_1.MainActivity" >

android:id="@+id/viewpager"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center" />

其中 是ViewPager对应的组件,要将其放到想要滑动的位置

2、新建三个layout,用于滑动切换的视图从效果图中也可以看到,我们的三个视图都非常简单,里面没有任何的控件,大家当然可以往里添加各种控件,但这里是个DEMO,只详解原理即可,所以我这里仅仅用背景来区别不用layout布局。

布局代码分别如下:

layout1.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ffffff"

android:orientation="vertical" >

layout2.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ffff00"

android:orientation="vertical" >

layout3.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#ff00ff"

android:orientation="vertical" >

二、代码实战先上整体代码,然后逐步讲解。

package com.example.testviewpage_1;

import java.util.ArrayList;

import java.util.List;

import java.util.zip.Inflater;

import android.app.Activity;

import android.os.Bundle;

import android.support.v4.view.PagerAdapter;

import android.support.v4.view.ViewPager;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

public class MainActivity extends Activity {

private View view1, view2, view3;

private ViewPager viewPager; //对应的viewPager

private List viewList;//view数组

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

viewPager = (ViewPager) findViewById(R.id.viewpager);

LayoutInflater inflater=getLayoutInflater();

view1 = inflater.inflate(R.layout.layout1, null);

view2 = inflater.inflate(R.layout.layout2,null);

view3 = inflater.inflate(R.layout.layout3, null);

viewList = new ArrayList();// 将要分页显示的View装入数组中

viewList.add(view1);

viewList.add(view2);

viewList.add(view3);

PagerAdapter pagerAdapter = new PagerAdapter() {

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

// TODO Auto-generated method stub

return arg0 == arg1;

}

@Override

public int getCount() {

// TODO Auto-generated method stub

return viewList.size();

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object) {

// TODO Auto-generated method stub

container.removeView(viewList.get(position));

}

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

container.addView(viewList.get(position));

return viewList.get(position);

}

};

viewPager.setAdapter(pagerAdapter);

}

}

代码量很小,全部放在了OnCreate()函数中。

1、先看声明的变量的意义:

private View view1, view2, view3;

private List viewList;//view数组

private ViewPager viewPager; //对应的viewPager

首先viewPager对应 控件。

view1,view2 ,view3对应我们的三个layout,即layout1.xml,layout2.xml,layout3.xml

viewList是一个View数组,盛装上面的三个VIEW

2、接下来是他们的初始化过程:

viewPager = (ViewPager) findViewById(R.id.viewpager);

LayoutInflater inflater=getLayoutInflater();

view1 = inflater.inflate(R.layout.layout1, null);

view2 = inflater.inflate(R.layout.layout2,null);

view3 = inflater.inflate(R.layout.layout3, null);

viewList = new ArrayList();// 将要分页显示的View装入数组中

viewList.add(view1);

viewList.add(view2);

viewList.add(view3);

初始化过程难度不大,就是将资源与变量联系起来布局,最后将实例化的view1,view2,view3添加到viewList中

3、PageAdapter——PageView的适配器适配器这个东东想必大家都不莫生,在ListView中也有适配器,listView通过重写GetView()函数来获取当前要加载的Item。而PageAdapter不太相同,毕竟PageAdapter是单个VIew的合集。

PageAdapter 必须重写的四个函数:

(1)boolean isViewFromObject(View arg0, Object arg1)

(2)int getCount()

(3)void destroyItem(ViewGroup container, int position,Object object)

(4)Object instantiateItem(ViewGroup container, int position)

先看看各个函数,我们上面都做了什么吧:

@Override

public int getCount() {

// TODO Auto-generated method stub

return viewList.size();

}

getCount():返回要滑动的VIew的个数

@Override

public void destroyItem(ViewGroup container, int position,

Object object) {

// TODO Auto-generated method stub

container.removeView(viewList.get(position));

}

destroyItem():从当前container中删除指定位置(position)的View;

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

container.addView(viewList.get(position));

return viewList.get(position);

}

};

instantiateItem():做了两件事,第一:将当前视图添加到container中,第二:返回当前View

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

// TODO Auto-generated method stub

return arg0 == arg1;

}

isViewFromObject():对于这个函数就先不做讲解,大家目前先知道它要这样重写就行了,后面我们会对它进行改写。

下面将仔细讲解这几个函数的意义,与有关Key的知识。

ViewPager的四大函数一、官方说明PagerAdapter比AdapterView的使用更加普通.ViewPager使用回调函数来表示一个更新的步骤,而不是使用一个视图回收机制。在需要的时候pageradapter也可以实现视图的回收或者使用一种更为巧妙的方法来管理视图,比如采用可以管理自身视图的fragment。

viewpager不直接处理每一个视图而是将各个视图与一个键联系起来。这个键用来跟踪且唯一代表一个页面,不仅如此,该键还独立于这个页面所在adapter的位置。当pageradapter将要改变的时候他会调用startUpdate函数,接下来会调用一次或多次的instantiateItem或者destroyItem。最后在更新的后期会调用finishUpdate。当finishUpdate返回时 instantiateItem返回的对象应该添加到父ViewGroup destroyItem返回的对象应该被ViewGroup删除。methodisViewFromObject(View, Object)代表了当前的页面是否与给定的键相关联。

对于非常简单的pageradapter或许你可以选择用page本身作为键,在创建并且添加到viewgroup后instantiateItem方法里返回该page本身即可

destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接可以返回view == object。

pageradapter支持数据集合的改变,数据集合的改变必须要在主线程里面执行,然后还要调用notifyDataSetChanged方法。和baseadapter非常相似。数据集合的改变包括页面的添加删除和修改位置。viewpager要维持当前页面是活动的,所以你必须提供getItemPosition方法。

二、解析viewpager不直接处理每一个视图而是将各个视图与一个键联系起来。这个键用来跟踪且唯一代表一个页面,不仅如此,该键还独立于这个页面所在adapter的位置。当pageradapter将要改变的时候他会调用startUpdate函数,接下来会调用一次或多次的instantiateItem或者destroyItem。最后在更新的后期会调用finishUpdate。当finishUpdate返回时 instantiateItem返回的对象应该添加到父ViewGroup destroyItem返回的对象应该被ViewGroup删除。methodisViewFromObject(View, Object)代表了当前的页面是否与给定的键相关联。

对于非常简单的pageradapter或许你可以选择用page本身作为键,在创建并且添加到viewgroup后instantiateItem方法里返回该page本身即可destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接可以返回view == object。

对于上面两段话,我这里有两点要着重讲一下:

1、第一段说明了,键(Key)的概念,首先这里要清楚的一点是,每个滑动页面都对应一个Key,而且这个Key值是用来唯一追踪这个页面的,也就是说每个滑动页面都与一个唯一的Key一一对应。大家先有这个概念就好,关于这个Key是怎么来的,下面再讲。

2、第二段简单讲了一个应用,即将当前页面本身的View作为Key。其实这个应用就是我们前一章讲的例子应用。不太理解?没关系,下面细讲。下面我们讲讲Key的问题。

三、关于Key现在我带着大家看看几个方法的官方文档:

1.首先,destroyItem():

该方法实现的功能是移除一个给定位置的页面。适配器有责任从容器中删除这个视图。这是为了确保在finishUpdate(viewGroup)返回时视图能够被移除。

在引入部分的例子中我们是这样做的:

@Override

public void destroyItem(ViewGroup container, int position,

Object object) {

// TODO Auto-generated method stub

container.removeView(viewList.get(position));

}

果不其然,我们将给定位置的视图从container中移除了……

2.然后看getCount ():

public abstract int getCount ()

Return the number of views available.

返回当前有效视图的个数。然后我们还:

@Override

public int getCount() {

// TODO Auto-generated method stub

return viewList.size();

}

返回了当前要滑动视图的个数,与官方说明一致。

四、最难的两个来了

1.instantiateItem (ViewGroup container, int position)这个函数的实现的功能是创建指定位置的页面视图。适配器有责任增加即将创建的View视图到这里给定的container中,这是为了确保在finishUpdate(viewGroup)返回时this is be done!

返回值:返回一个代表新增视图页面的Object(Key),这里没必要非要返回视图本身,也可以这个页面的其它容器。其实我的理解是可以代表当前页面的任意值,只要你可以与你增加的View一一对应即可,比如position变量也可以做为Key(最后我们举个例子试试可不可行)

心得 :

(1)从说明中可以看到,在代码中,我们的责任是将指定position的视图添加到conatiner中

(2)Key的问题:从这个函数就可以看出,该函数返回值就是我们根据参数position增加到conatiner里的View的所对应的Key!!!!!!!

(3)“it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup).”这句话在destroyItem()的函数说明中同样出现过,这说明在 finishUpdate(viewGroup)执行完后,有两个操作,一个是原视图的移除(不再显示的视图),另一个是新增显示视图(即将显示的视图)

还是一开始引入的例子中,我们是这样做的:

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

container.addView(viewList.get(position));

return viewList.get(position);

}

};

在这里,我们做了两件事

第一:将参数里给定的position的视图,增加到conatiner中,供其创建并显示、。

第二:返回当前position的View做为此视图的Key。还记得API官方文档中下面这段话么?

对于非常简单的pageradapter或许你可以选择用page本身作为键,在创建并且添加到viewgroup后instantiateItem方法里返回该page本身即可destroyItem将会将该page从viewgroup里面移除。isViewFromObject方法里面直接可以返回view == object。

这里就把当前的View当作Key传过出去!!!!

2.isViewFromObject (View view, Object object)功能:该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View)

返回值:如果对应的是同一个View,返回True,否则返回False。

在上面的例子中,我们这样做的:

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

// TODO Auto-generated method stub

return arg0 == arg1;

}

由于在instantiateItem()中,我们作为Key返回来的是当前的View,所以在这里判断时,我们直接将Key与View看是否相等来判断是否是同一个View。

五、自定义Key实例经过上面的讲解,想必大家给Key的概念应该有个清楚的理解,下面举个例子来说明Key与View的关系,由于Key与View要一一对应,所以我把每个视图所处的位置Position作为Key,在上章例子的基础上更改的,下面先看全部代码,然后看部分讲解:

package com.example.testviewpage_2;

import java.util.ArrayList;

import java.util.List;

import android.app.Activity;

import android.os.Bundle;

import android.support.v4.view.PagerAdapter;

import android.support.v4.view.ViewPager;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

public class MainActivity extends Activity {

private View view1, view2, view3;

private List viewList;// view数组

private ViewPager viewPager; // 对应的viewPager

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

viewPager = (ViewPager) findViewById(R.id.viewpager);

LayoutInflater inflater = getLayoutInflater();

view1 = inflater.inflate(R.layout.layout1, null);

view2 = inflater.inflate(R.layout.layout2, null);

view3 = inflater.inflate(R.layout.layout3, null);

viewList = new ArrayList();// 将要分页显示的View装入数组中

viewList.add(view1);

viewList.add(view2);

viewList.add(view3);

PagerAdapter pagerAdapter = new PagerAdapter() {

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

// TODO Auto-generated method stub

//根据传来的key,找到view,判断与传来的参数View arg0是不是同一个视图

return arg0 == viewList.get((int)Integer.parseInt(arg1.toString()));

}

@Override

public int getCount() {

// TODO Auto-generated method stub

return viewList.size();

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object) {

// TODO Auto-generated method stub

container.removeView(viewList.get(position));

}

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

container.addView(viewList.get(position));

//把当前新增视图的位置(position)作为Key传过去

return position;

}

};

viewPager.setAdapter(pagerAdapter);

}

}

在这里更改了两个地方:

1、先看Key的产生的位置instantiateItem()

@Override

public Object instantiateItem(ViewGroup container, int position) {

// TODO Auto-generated method stub

container.addView(viewList.get(position));

//把当前新增视图的位置(position)作为Key传过去

return position;

}

我们在上讲也讲了在这个函数中Key是作为返回值与当前装入Container中的视图对应起来的。所以在这里我们返回postion与container.addView(viewList.get(position));里的viewList.get(position)这个视图对应起来。

2、isViewFromObject ()

@Override

public boolean isViewFromObject(View arg0, Object arg1) {

// TODO Auto-generated method stub

//根据传来的key,找到view,判断与传来的参数View arg0是不是同一个视图

return arg0 == viewList.get((int)Integer.parseInt(arg1.toString()));

}

判断从instantiateItem()返回来的Key与当前的View是否能对应起来,我们知道从instantiateItem传过来的其实是position,所以我们要根据position找到View,然后跟参数中的View arg0判断。

但在真正操作时出现了问题,我们要先将obect对应转换为int类型:(int)Integer.parseInt(arg1.toString());然后再根据position找到对应的View;

效果图:三个View之间的滑动切换

80da40d7cf5c715d1449a8202e293e24.png

ec50fcbd2057b37d6f8337b3c2a9b24c.png

这里只所以与上章不一样,仅仅只有上部分一部分的地方才有滑动切换,是因为我更改了布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.example.testviewpage_2.MainActivity" >

android:id="@+id/viewpager"

android:layout_width="wrap_content"

android:layout_height="200dip"

android:layout_gravity="center" />

这里将layout_height更改为200dip,只所以这么做,是为了告诉大家,只要在想要实现滑动切换的地方添加上就可以实现切换,无所谓位置和大小,跟普通控件一样!!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值