Android 利用PagerView做引导页
先看实际效果,这个是用了一个APP里面的图片,不是自己的图。
第一步:创建引导页的 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"