Android 利用PagerView做引导页

先看实际效果,这个是用了一个APP里面的图片,不是自己的图。

Android 利用PagerView做引导页

第一步:创建引导页的 Activity,先在引导页上的xml定义一个ViewPager和用于下面放置圆点导航的ViewImage。

<android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:background="#00000000">
    </android.support.v4.view.ViewPager>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="68dp"
        >

        <ImageView
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:id="@+id/iv1"
            android:src="@drawable/abc_btn_radio_check"/>
        <ImageView
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:id="@+id/iv2"
            android:src="@drawable/abc_btn_radio_nocheck"/>
        <ImageView
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:id="@+id/iv3"
            android:src="@drawable/abc_btn_radio_nocheck"/>
        <ImageView
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:id="@+id/iv4"
            android:src="@drawable/abc_btn_radio_nocheck"/>
    
    </LinearLayout>

第二步:创建一个继承自 PagerAdapter 的类。其中的内容也是分3个部分:
第1部分:构造函数
第2部分:加载、销毁View的方法
第3部分:自动生成的两个有返回值的方法

public class ViewPagerAdapter extends PagerAdapter {

    // 创建两个变量,作为参数传入构造方法
    private List<View> mViews;
    private Context mContext;


    public ViewPagerAdapter (List<View> views, Context context) {
        this.mViews = views;
        this.mContext = context;
    }

    // 根据 position 索引来销毁View
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mViews.get(position));
    }

    // 加载 View
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mViews.get(position));
        return mViews.get(position);
    }

    // 返回 View 集合的数量
    @Override
    public int getCount() {
        return mViews.size();
    }

    // 判断当前 View 是否我们需要的对象
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view == object);
    }
}

第三步:回到刚才引导页的Activity,添加如下代码。

public class GuideActivity extends Activity implements ViewPager.OnPageChangeListener {

    private ViewPager mViewPager;
    private ViewPagerAdapter mViewPagerAdapter;
    private List<View> mViews;
    private ImageView[] mImageViews;
    private int[] mInts = new int[] {R.id.iv1, R.id.iv2, R.id.iv3, R.id.iv4};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 去除引导页的标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 设置顶部状态栏为透明状态
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_guide);
        // 加载View视图
        initViews();
        // 加载底部圆点导航
        initPoint();
    }

    // 加载 View 视力
    private void initViews() {
        //第1步,创建一个View的集合,并动态加载n个View,添加进集合
        LayoutInflater inflater = LayoutInflater.from(this);
        mViews = new ArrayList<View>();
        mViews.add(inflater.inflate(R.layout.layout_guide_0, null));
        mViews.add(inflater.inflate(R.layout.layout_guide_1, null));
        mViews.add(inflater.inflate(R.layout.layout_guide_2, null));
        mViews.add(inflater.inflate(R.layout.layout_guide_3, null));
        ////第2步,为ViewAdapter装载这个集合
        mViewPagerAdapter = new ViewPagerAdapter(mViews, this);
        //第3步,给ViewPager设置ViewAdapter
        mViewPager = (ViewPager) findViewById(R.id.viewPager);
        mViewPager.setAdapter(mViewPagerAdapter);

        // 找到 Button,注意这个 Button 不是当前布局里的,这个按钮是在集合中最后一页的进入首页那个按钮
        // 所以得用 view 集合找到最后一页再 findViewById,不然会因找不到,导致空指针异常。
        Button btnEntryMain = (Button) mViews.get(3).findViewById(R.id.btnEntryMain);
        btnEntryMain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(GuideActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }
        });
        mViewPager.setOnPageChangeListener(this);
    }

    // 加载底部圆点导航
    private void initPoint() {
        mImageViews = new ImageView[mViews.size()];
        for (int i = 0; i < mViews.size(); i++) {
            mImageViews[i] = (ImageView) findViewById(mInts[i]);
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    // 当Page被选中时解发的事,变换圆点导航
    @Override
    public void onPageSelected(int position) {
        for (int i = 0; i < mImageViews.length; i++) {
            if (position == i){
                mImageViews[i].setImageResource(R.drawable.abc_btn_radio_check);
            } else {
                mImageViews[i].setImageResource(R.drawable.abc_btn_radio_nocheck);
            }
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

第四步:这里开始创建要显示View的xml,这里用到了4个xml,都是一样的代码,唯独最后一个多添加了一个用于进入主Activity的Button,故只贴出最后一个xml的代码。

<android.support.percent.PercentRelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <ImageView
        android:id="@+id/ivFont"
        app:layout_widthPercent="60%"
        app:layout_heightPercent="30%"
        android:layout_centerInParent="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="70dp"
        android:src="@drawable/guide_p4_word"/>

    <ImageView
        android:id="@+id/ivImage"
        android:layout_below="@id/ivFont"
        app:layout_widthPercent="100%"
        app:layout_heightPercent="30%"
        android:src="@drawable/guide_p4_img"/>

    <Button
        android:id="@+id/btnEntryMain"
        app:layout_widthPercent="80%"
        android:layout_height="wrap_content"
        android:text="进入主程序"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="15dp"
        android:layout_centerHorizontal="true"
        android:textSize="20sp"
        android:background="#cac2c8"
        android:textColor="@color/colorPrimary"/>


</android.support.percent.PercentRelativeLayout>

这里用的布局是百分比布局,适配性还是不行,如果在特别大的屏幕,会有一点点的小偏差,待后期做整个Demo的时候再好好改改。

第五步,这里再创建一个Activity,用于进程序显示的第一个画面,可以放张图片或者广告之类的。

public class WelcomeActivity extends Activity {

    private static final int WAIT_TIME = 2000;
    private static final int ACT_HOME = 1000;
    private static final int ACT_GUIDE = 1001;
    private boolean mIsFirst = false;

    // 延时操作启动相关的 Activity,因为是在主线程,所以用 Handler
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
                case ACT_HOME:
                    goHome();
                    break;
                case ACT_GUIDE:
                    goGuide();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 去掉头部标题
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 设置头部状态栏透明(同色)
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        setContentView(R.layout.activity_wecome);
        init();
    }

    // 根据 SharedPreferences 的 first 发送给 Handler 启动哪个 Activity
    private void init() {
        SharedPreferences sp = getPreferences(MODE_PRIVATE);
        //先去取isFirst的值,如果没有,表明是第一次取,第一次取肯定是true,所以这里给个默认值为 true
        mIsFirst = sp.getBoolean("first", true);
        if (!mIsFirst){
            // 有延时
            mHandler.sendEmptyMessageDelayed(ACT_HOME, WAIT_TIME);
        } else {
            // 直接启动
            mHandler.sendEmptyMessage(ACT_GUIDE);
            // 写入数据
            SharedPreferences.Editor editor = sp.edit();
            editor.putBoolean("first", false);
            editor.commit();
        }
    }

    // 启动主 Activity
    private void goHome() {
        Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);
        startActivity(intent);
        finish();
    }

    // 启动引导页 Activity
    private void goGuide() {
        Intent intent = new Intent(WelcomeActivity.this, GuideActivity.class);
        startActivity(intent);
        finish();
    }
}

如果想简化一点,可以不必创建这个 Activity ,有另一种解决方法:
在style.xml 文件中新建一个style 主题

<style name="Theme.Start" parent="android:Theme">  
    <item name="android:windowBackground">@drawable/ic_launcher</item>  
    <item name="android:windowNoTitle">true</item>  
</style>

android:windowBackgrounds属性中添加自己的过场图片就好
在AndroidManifest.xml文件, 程序中第一个显示的界面添加这个主题

<application  
    android:allowBackup="true"  
    android:icon="@drawable/ic_launcher"  
    android:label="@string/app_name"  
    android:theme="@style/AppTheme" >  
    <activity  
        android:name=".ActLogo"  
        android:theme="@style/Theme.Start" >  
        <intent-filter>  
            <action android:name="android.intent.action.MAIN" />  
  
            <category android:name="android.intent.category.LAUNCHER" />  
        </intent-filter>  
    </activity>  
</application>

当然了,用这种方法的话,WelcomeActivity里的业务逻辑代码就得放进MainActivity里,看自己怎么去做,业务逻辑还是一样的。

另外做好后还是遇到了一个问题,就是在启动程序的时候会有1秒左右的空白,这个很好解决,在AndroidManifest.xml定义要启动的 Activity 里加上一个主题即可。

android:theme="@android:style/Theme.Translucent"

相关推荐