Android进阶篇之引导页系列之ViewPager静态引导

本文探讨了在Android开发中如何实现ViewPager静态引导页,并详细讲述了ViewPager的工作原理,包括页面加载策略和内存管理。作者通过实例分享了如何处理可能导致内存溢出的问题,特别是涉及大图和动画时。此外,文章还预告了后续将讨论更复杂的ViewPager动画引导页和SurfaceView动画引导页。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引导页???这是多少人写过的啊,还写,猪吗?

相信很多小伙伴就已经火大了。大哭

其实呢,主要是我进入职场的头一个月基本上就全泡在了引导页上,遇见过各种奇葩心塞的bug

所以在此,想写一系列关于此类的博文

基本路线是:先从ViewPager静态引导页讲起,然后是ViewPager静态页的翻页动画,ViewPager简单动画引导页,SurfaceView复杂型动画引导页

废话不多说,一步步来。先来看看guide_layout.xml文件,这个是引导页的显示页

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <android.support.v4.view.ViewPager
        android:id="@+id/guide_view_group"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        
    </android.support.v4.view.ViewPager>

</LinearLayout>
里面就是一个ViewPager,如果没有v4的包,需要自己动态添加以下,这里就不介绍怎么添加v4包了

然后看看引导页的子页,就是滑动的每一页的布局文件,guide_item_view.xml,个人比较懒所以会对这个布局进行复用,形成4个子页。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >
    
    <TextView android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="48sp"
        android:text="0"/>

</LinearLayout>

然后来看看Java代码,其实基础型的引导页结构还是很简单的

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class GuidanceActivity extends Activity{

	private ViewPager mViewPager ;
	private PagerAdapter mPagerAdapter ;
	private List<View> mListViews ;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.guide_layout) ;
		mListViews = new ArrayList<View>() ;
		LayoutInflater inflater = getLayoutInflater() ;
		View view1 = inflater.inflate(R.layout.guide_item_view, null) ;
		view1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark)) ;
		((TextView) view1.findViewById(R.id.tv)).setText("0") ;
		
		View view2 = inflater.inflate(R.layout.guide_item_view, null) ;
		view2.setBackgroundColor(getResources().getColor(android.R.color.holo_red_dark)) ;
		((TextView) view2.findViewById(R.id.tv)).setText("1") ;
		
		View view3 = inflater.inflate(R.layout.guide_item_view, null) ;
		view3.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_dark)) ;
		((TextView) view3.findViewById(R.id.tv)).setText("2") ;
		
		View view4 = inflater.inflate(R.layout.guide_item_view, null) ;
		view4.setBackgroundColor(getResources().getColor(android.R.color.holo_green_dark)) ;
		((TextView) view4.findViewById(R.id.tv)).setText("3") ;
		
		mListViews.add(view1) ;
		mListViews.add(view2) ;
		mListViews.add(view3) ;
		mListViews.add(view4) ;
		
		mViewPager = (ViewPager) findViewById(R.id.guide_view_group); 
		mPagerAdapter = new PagerAdapter(mListViews) ;
		mViewPager.setAdapter(mPagerAdapter) ;
	}
	
	private class PagerAdapter extends android.support.v4.view.PagerAdapter {

		private List<View> mViews ;
		
		public PagerAdapter(List<View> views) {
			super() ;
			mViews = views ;
		}
		
		@Override
		public int getCount() {
			return mViews.size();
		}

		@Override
		public boolean isViewFromObject(View v, Object obj) {
			return v == obj;
		}
		
		@Override
		public void destroyItem(View view, int position, Object object) {
			((ViewPager) view).removeView(mViews.get(position)); 
		}
		
		@Override
		public Object instantiateItem(View view, int position) {
			
			((ViewPager) view).addView(mViews.get(position), 0);  
	        return mViews.get(position);  
		}
	}
}

最后来分析分析,

mListViews装你想要显示的几个子页,我这里写了4个页面

private List<View> mListViews ;

获取inflater对象来初始化四个View,inflater可以有很多种方式获取,在Activity中可以直接getLayoutInflater(),如果只是在某个View中想获取此对象,可以使用Context<这是上下文,也是一个很重要很重要的家伙>,以后再专门讲讲

LayoutInflater inflater = getLayoutInflater() ;
		View view1 = inflater.inflate(R.layout.guide_item_view, null) ;
		view1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark)) ;
		((TextView) view1.findViewById(R.id.tv)).setText("0") ;
		
		View view2 = inflater.inflate(R.layout.guide_item_view, null) ;
		view2.setBackgroundColor(getResources().getColor(android.R.color.holo_red_dark)) ;
		((TextView) view2.findViewById(R.id.tv)).setText("1") ;
		
		View view3 = inflater.inflate(R.layout.guide_item_view, null) ;
		view3.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_dark)) ;
		((TextView) view3.findViewById(R.id.tv)).setText("2") ;
		
		View view4 = inflater.inflate(R.layout.guide_item_view, null) ;
		view4.setBackgroundColor(getResources().getColor(android.R.color.holo_green_dark)) ;
		((TextView) view4.findViewById(R.id.tv)).setText("3") ;
之后就来讲讲PagerAdapter,在类中自己新建一个Adapter类继承v4包中的PagerAdapter

		public PagerAdapter(List<View> views) {
			super() ;
			mViews = views ;
		}
上面的代码是指在adapter初始化的时候,将之前定义的四个view的容器mListViews传进来

然后,在Adapter里面分别对每一个view操作即可

		@Override
		public int getCount() {
			return mViews.size();
		}
获取有多少个子页。

		@Override
		public boolean isViewFromObject(View v, Object obj) {
			return v == obj;
		}
这个方法呢,说白了就是为了看public Object instantiateItem(View view, int position)这个方法返回的object是否和view有关,额,如果想深入了解的话,最好直接看看源码

		@Override
		public Object instantiateItem(View view, int position) {
			
			((ViewPager) view).addView(mViews.get(position), 0);  
	        return mViews.get(position);  
		}
动态加入每一个子页view,看这个函数返回的对象是Object就知道,这个函数不一定就是返回view,也可以是其他的

还有一个函数,虽然在demo中可加,可不加。但是也是让人头疼的,也是让人喜欢的函数

		@Override
		public void destroyItem(View view, int position, Object object) {
			((ViewPager) view).removeView(mViews.get(position)); 
		}

先说它的作用,在吐槽吐槽。

其实在ViewPager中对引导页是只加载当前页的下一页和上一页的,其他的页都会直接调用此函数摧毁掉,也可以看做是做释放内存的操作。

像这种摧毁性的和释放性的函数,是很让人不喜欢的,因为一旦它出现了,势必就要深刻理会它们的重要性,理由只有一个,因为它们直接和你的代码中的bug数联系上了

其实在demo中对他的需求还不是很明显,因为一个demo就是引导页,所以对内存的分配可以土豪点,但是当引导页仅仅是作为程序中很小很小的一部分时,那我就要重新审视它们了。

讲一个案例:我在写动态引导页的时候,由于背景xxh的比较大,所以直接加到内存中,然后再有许多页面中的动画,程序立马outofmemory,内存溢出了,这个是很头疼的一件事,特别是在动画页中还有AnimationDrawable动画的时候,需要特别的小心,所以就要终点使用destroyItem函数了,上面的例子在此函数里面只是做摧毁item页面的操作,其实在实际中,要做的还有很多资源内存回收的操作,因为这些资源你不去主动释放,哪怕是在你的引导页不报outofmemeory,一旦进入程序,加载一些其他的资源很大可能就Crash掉了。这些在之后的博文中一一列出。

今天就到这里了,把代码放上来:代码下载,都是不要钱的哟,小伙伴们捧个场就行了!大笑














评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值