Android UI开发第二十篇——仿launcher的左右滑动(用ViewPager实现欢迎引导页面)

        Android提供另一个非常有用的控件ViewPager。使用这个控件,需要用到google提到的一个包——android-support-v4.jar,这个包中包含了一些非常有用的类,其中就是ViewPager类来实现页面之间的切换操作,关于android-support-v4.jar的详细信息,大家可以访问google官方网站: http://developer.android.com/sdk/compatibility-library.html。 
        具体的把Android提供的android-support-v4.jar导入工程,并add build path的方法这里不做介绍,可以参考以上提供的网址,里面会有详细的说明,步骤比较简单。
        下面通过两个例子来讲解一下比较复杂的滑动界面的实现。

一、Demo1


 
                  Demo1运行效果1                                     Demo1运行效果2
Demo1实现的效果是我们在浏览新闻网页时经常会看到的,屏幕的上半部分是图片,下半部分是文字的介绍,而顶部是一个导航的工具栏可以供用户选择退出或者回到主菜单等。用户通过左右的滑动屏幕,实现翻页的效果。而在屏幕的最底部,会有对当前所处页面的指示标记。
主布局文件main.xml的内容如下:

xml代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <include
            android:id="@+id/item_header"
            layout="@layout/item_header" />

        <android.support.v4.view.ViewPager
            android:id="@+id/myviewpager"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <LinearLayout
                android:id="@+id/mybottomviewgroup"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="40dp"
                android:gravity="center_horizontal"
                android:orientation="horizontal" >
            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>

</FrameLayout>

最外层是LinearLayout,其中包括两个Linearlayout,第一个LinearLayout是显示新闻的主界面,而第二个LinearLayout是为了在底部存放指示当前界面的标记图片。值得注意的是第一个LinearLayout中包括又包括两部分,一个是通过include引入的item_header视图,一个是ViewPager控件,在这里还要注意ViewPager空间的布局方式。代码如下:

xml代码:

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <include
        android:id="@+id/item_header"
        layout="@layout/item_header" />

    <android.support.v4.view.ViewPager
        android:id="@+id/myviewpager"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

另外,在layout文件夹下还定义了item01——item06六个布局文件作为ViewPager的六个页面,在JAVA代码中会把它们分别添加进ViewPager。Item_header.xml布局定义了屏幕上方的导航栏,通过include的方式引入了main.xml布局文件。

java代码:

package com.devdiv.test.ui_test_viewpager;

import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.ImageView;

public class UI_Test_ViewPagerActivity extends Activity {

	private ViewPager mViewPager;
	private ArrayList<View> mPageViews;
	private ImageView mImageView;
	private ImageView[] mImageViews;

	// 该应用的主布局LinearLayout
	private ViewGroup mainViewGroup;
	// 主布局底部指示当前页面的小圆点视图,LinearLayout
	private ViewGroup indicatorViewGroup;

	// 定义LayoutInflater
	LayoutInflater mInflater;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// setContentView(R.layout.main);
		// 设置窗口无标题
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// mInflater = (LayoutInflater)
		// getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		mInflater = getLayoutInflater();
		mPageViews = new ArrayList<View>();
		mPageViews.add(mInflater.inflate(R.layout.item01, null));
		mPageViews.add(mInflater.inflate(R.layout.item02, null));
		mPageViews.add(mInflater.inflate(R.layout.item03, null));
		mPageViews.add(mInflater.inflate(R.layout.item04, null));
		mPageViews.add(mInflater.inflate(R.layout.item05, null));
		mPageViews.add(mInflater.inflate(R.layout.item06, null));
		mImageViews = new ImageView[mPageViews.size()];

		mainViewGroup = (ViewGroup) mInflater.inflate(R.layout.main, null);
		mViewPager = (ViewPager) mainViewGroup.findViewById(R.id.myviewpager);
		indicatorViewGroup = (ViewGroup) mainViewGroup
				.findViewById(R.id.mybottomviewgroup);

		for (int i = 0; i < mImageViews.length; i++) {
			mImageView = new ImageView(UI_Test_ViewPagerActivity.this);
			mImageView.setLayoutParams(new LayoutParams(20, 20));
			mImageView.setPadding(20, 0, 20, 0);

			if (i == 0) {
				mImageView
						.setBackgroundResource(R.drawable.page_indicator_focused);
			} else {
				mImageView.setBackgroundResource(R.drawable.page_indicator);
			}
			mImageViews[i] = mImageView;

			// 把指示作用的远点图片加入底部的视图中
			indicatorViewGroup.addView(mImageViews[i]);
		}

		// 注意这两种用法的区别,前者无法正常显示!!
		// setContentView(R.layout.main);
		setContentView(mainViewGroup);

		mViewPager.setAdapter(new MyPagerAdapter());
		mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
			@Override
			public void onPageSelected(int arg0) {
				for (int i = 0; i < mImageViews.length; i++) {
					if (i == arg0) {
						mImageViews[i]
								.setBackgroundResource(R.drawable.page_indicator_focused);
					} else {
						mImageViews[i]
								.setBackgroundResource(R.drawable.page_indicator);
					}
				}
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int arg0) {
			}
		});
	}

	class MyPagerAdapter extends PagerAdapter {
		@Override
		public int getCount() {
			return mPageViews.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}

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

		@Override
		public void destroyItem(View arg0, int arg1, Object arg2) {
			((ViewPager) arg0).removeView(mPageViews.get(arg1));
		}

		@Override
		public Object instantiateItem(View arg0, int arg1) {
			((ViewPager) arg0).addView(mPageViews.get(arg1));
			return mPageViews.get(arg1);
		}

		@Override
		public void restoreState(Parcelable arg0, ClassLoader arg1) {
		}

		@Override
		public Parcelable saveState() {
			return null;
		}

		@Override
		public void startUpdate(View arg0) {
		}

		@Override
		public void finishUpdate(View arg0) {
		}
	}
}

        其中,需要注意的是在自定义MyPagerAdapter继承自PagerAdapter,需要重写其中的一些重要方法,可以类比BaseAdapter的实现便于理解,具体实现参考API文档。

java代码:

			mImageViews = new ImageView[mPageViews.size()];
	        
	        mainViewGroup = (ViewGroup) mInflater.inflate(R.layout.main, null);
	        
	        mViewPager = (ViewPager) mainViewGroup.findViewById(R.id.myviewpager);
	        indicatorViewGroup = (ViewGroup) mainViewGroup.findViewById(R.id.mybottomviewgroup);
	        
	        for (int i = 0; i < mImageViews.length; i++) {
		         mImageView = new ImageView(UI_Test_ViewPagerActivity.this);  
		         mImageView.setLayoutParams(new LayoutParams(20,20));  
		         mImageView.setPadding(20, 0, 20, 0);  
		         
		         if (i == 0) {
		        	 mImageView.setBackgroundResource(R.drawable.page_indicator_focused);    
	   } else {
		   mImageView.setBackgroundResource(R.drawable.page_indicator);
	   }
	   
	   mImageViews[i] = mImageView;
	     
	   //把指示作用的远点图片加入底部的视图中
	   indicatorViewGroup.addView(mImageViews[i]);
  }

根据mPageViews的大小初始化ImageViews,也就是说ViewPager中存在几个Page就初始化几个圆点的图片进行相应的指示。并且根据位置,设置圆点的不同状态,出事情况下显示第一个Page,因此第一个圆点的图片是focused的状态。最后,通过indicatorViewGroup.addView(mImageViews[i])把所有圆点的图片添加到布局中,在屏幕上显示。 
底部圆点图片初始化并加入布局后,需要给ViewPager设置Adapter,这里使用的是我们自定义的MyPagerAdapter,然后执行setContentView操作。
最后,为了是底部的圆点视图具有指示作用,需要为ViewPager设置监听器,来根据ViewPager的不同状态,改变底部圆点视图的状态。代码如下:

java代码:

	mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
	   
	   @Override
	   public void onPageSelected(int arg0) {
		    // TODO Auto-generated method stub
		    for (int i = 0; i < mImageViews.length; i++) {
			     if(i == arg0) {
			    	 mImageViews[i].setBackgroundResource(R.drawable.page_indicator_focused);
			     } else {
			    	 mImageViews[i].setBackgroundResource(R.drawable.page_indicator);
			     }
		    }
	   }
	   
	   @Override
	   public void onPageScrolled(int arg0, float arg1, int arg2) {
	   }
	   
	   @Override
	   public void onPageScrollStateChanged(int arg0) {
	   }
	});

二、Demo2
       
        Demo2同样实现了左右滑动的效果,不过我们在不同的页面使用了不同的布局,这在实际的应用中也是很常见的。我们同样使用了ViewPager控件,具体方法和Demo1基本相同。
        不同在于,我们在两个页面中分别使用了ListView中GridView视图,并在代码中为它们分别绑定了不同的Adapter。ListView使用了简单的ArrayAdapter,显示一组数据。GridView使用了自定义的Adapter。
        由于Demo2和Demo1的内容非常相似,我们就不再展开分析。
        Demo2运行效果如下:
   
              第一个视图                             滑动过程中                            第二个视图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值