安卓开发 之小白养成-ViewPager详解

  • 什么是ViewPager和ViewPager使用场景

      ViewPage是v4扩展包中提供的一个控件。是一个ViewGroup,可以包含很多的View,当手指在屏幕上左右滑动的时候,可以切换页面。ViewPager一般与Fragment结合使用比较方便。

大家经常见到的app的引导界面通常会用到ViewPager技术。

  • 使用ViewPager

ViewPager的使用,与ListView使用类似,也需要绑定相应的适配器。

ViewPager 使用主要分3个步骤:

  1. 在布局文件中添加ViewPager控件。注意:写这个控件的时候要写全称(包名+类名)

<android.support.v4.view.ViewPager

                  android:id="@+id/pager"

                  android:layout_width="match_parent"

android:layout_height="match_parent" />

2.加载要显示的页面,并把要显示的页面放入数组或List 集合中。

    LayoutInflater lf = getLayoutInflater().from(this);  

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

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

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

      viewList = new ArrayList<View>();

      viewList.add(view1);  

      viewList.add(view2);  

      viewList.add(view3);  

3.在Activity里实例化ViewPager组件,并设置它的Adapter,一般需要重写PagerAdapter。

(和ListView使用方式差不多,使用步骤也类似。)

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_collection_demo);

 

        // ViewPager and its adapters use support library

        // fragments, so use getSupportFragmentManager.

        mDemoCollectionPagerAdapter =

                new DemoCollectionPagerAdapter(

                        getSupportFragmentManager());

        mViewPager = (ViewPager) findViewById(R.id.pager);

        mViewPager.setAdapter(mDemoCollectionPagerAdapter);

}

ViewPager的方法:----了解

  1. setAdapter():ViewPager 通过 setAdapter() 来建立与 PagerAdapter 的联系。这个联系是双向的,一方面,ViewPager 会拥有 PagerAdapter 对象,从而可以在需要时调用 PagerAdapter 的方法;另一方面,ViewPager 会在 setAdapter() 中调用 PagerAdapter 的 registerDataSetObserver() 方法,注册一个自己生成的 PagerObserver 对象,从而在 PagerAdapter 有所需要时(如 notifyDataSetChanged() 或 notifyDataSetInvalidated() 时),可以调用 Observer 的 onChanged() 或 onInvalidated() 方法,从而实现 PagerAdapter 向 ViewPager 方向发送信息。
  2. dataSetChanged():在 PagerObserver.onChanged(),以及 PagerObserver.onInvalide() 中被调用。因此当 PagerAdapter.notifyDataSetChanged() 被触发时,ViewPager.dataSetChanged() 也可以被触发。该函数将使用 getItemPosition() 的返回值来进行判断,如果为 POSITION_UNCHANGED,则什么都不做;如果为 POSITION_NONE,则调用 PagerAdapter.destroyItem() 来去掉该对象,并设置为需要刷新 (needPopulate = true) 以便触发 PagerAdapter.instantiateItem() 来生成新的对象。

  • PageAdapter

PageAdapter 是 ViewPager 的支持者,ViewPager 将调用它来取得所需显示的页,而 PageAdapter 也会在数据变化时,通知 ViewPager。这个类也是FragmentPagerAdapter 以及 FragmentStatePagerAdapter 的基类。如果继承该类,至少需要实现 instantiateItem(), destroyItem(), getCount() 以及 isViewFromObject()四个方法。

  1. nstantiateItem():在每次 ViewPager 需要一个用以显示的 Object 的时候,该方法都会被 ViewPager.addNewItem()方法 调用。该方法内部一定要把指定位置要显示的视图添加到ViewPager中。
  2. destroyItem():从当前的ViewPager容器中删除指定位置的View对象。
  3. getCount ():返回要滑动的View的个数。
  4. isViewFromObject():该方法用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View)     返回值:如果对应的是同一个View,返回True,否则返回False。
  • ViewPager添加标题
  1. 给ViewPager添加一个子标签

<android.support.v4.view.PagerTitleStrip

        android:id="@+id/pagertitle"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="top" />

注意:android:layout_gravity="top"  属性的值有top和bottom,表示把title放在ViewPager的顶部还是底部

  1. 覆写PageAdapter的getPageTitle(position)方法,该方法返回每个页面的title。

@Override

public CharSequence getPageTitle(int position) {

}

 

pagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.gold));//设置指示器的颜色

pagerTabStrip.setBackgroundColor(getResources().getColor(R.color.azure)); //设置标题背景色   

pagerTabStrip.setTextSpacing(50);//设置间距无效,不知道为什么。

注意:还有一种标题是android.support.v4.view.PagerTabStrip用法与上面的完全一样,唯一区别就是每个标题下面添加了一个下划线,并且标题也可点击

  • 给ViewPager添加监听器OnPageChangeListener

pager.setOnPageChangeListener(new OnPageChangeListener() {

/**

 * 当滑动结束后,新的pager完全显示到屏幕后会调用该方法

 *  参数:新的pager的index

 */

@Override

public void onPageSelected(int arg0) {

// Log.e(TAG, "onPageSelected..." + arg0);

}

 

/**

 * 当正在滑动时,会一直回调该方法

 * arg0 :当前页面,及你点击滑动的页面

 * arg1:当前页面偏移的百分比

 * arg2:当前页面偏移的像素位置

 */

@Override

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

// Log.e(TAG, "onPageScrolled..." + arg0 + "  " + arg1 + "   " + arg2);

}

/**

 * 当状态方法改变的时候调用

 * 参数:页面的状态

 * 共有三种状态:    

 * SCROLL_STATE_IDLE   页面静止的时候的状态

    SCROLL_STATE_DRAGGING  正在滑动的状态

     SCROLL_STATE_SETTLING  到了要滑动的最终位置的状态

 */

@Override

public void onPageScrollStateChanged(int arg0) {

//

 

Log.e(TAG, "onPageScrollStateChanged..." + msg);

                            if (state == ViewPager.SCROLL_STATE_DRAGGING

                 && viewPager.getCurrentItem()==viewPager.getChildCount() )

                //判断是否是最后一页

                           

}

});

动态创建radiobutton

RadioButton radioButton = new RadioButton(MainActivity.this);

radioButton.setId(i);

radioGroup.addView(radioButton);

动态设置radiobutton选中:

((RadioButton)radioGroup.getChildAt(0)).setChecked(true);

扩展实现首次运行软件的闪屏页面

  1. 欢迎页---停留2秒
  2. 判断是否是第一次运行软件
  3. 是的话 进入广告页(3-4张图片 能够指示位置,用小圆点图 用户滑动到最后一页进入主界面)
  4. 不是第一次运行 直接进入主界面

    

设置activity全屏

首先设置主题为Theme.AppCompat.Light.NoActionBar

增加<item name="android:windowFullscreen">true</item>

      //在按下返回键的时候会回调

public void onBackPressed() {

if (isFirst) {

Toast.makeText(this, "再按一次退出", 0).show();

lastTime = System.currentTimeMillis();

isFirst = false;

} else {

long currentTime = System.currentTimeMillis();

if (currentTime - lastTime <= 2000) {

finish();

} else {

Toast.makeText(this, "再按一次退出", 0).show();

lastTime = System.currentTimeMillis();

}

}

}

  • FragmentPagerAdapter的使用

FragmentPagerAdapter是PagerAdapter的其中一种实现。它将每一个页面表示为一个 Fragment,并且每一个Fragment都将会保存到fragmentManager当中。而且,当用户没可能再次回到页面的时候,fragmentManager才会将这个Fragment销毁。

   让Fragment 成为ViewPager的一页时,FragmentManager会一直保存管理创建好了的Fragment,即使当前不是显示的这一页,Fragment对象也不会被销毁,在后台默默等待重新显示。但如果Fragment不再可见时,它的视图层次会被销毁掉,下次显示时视图会重新创建。

这种pager十分适用于有一些静态fragment,例如一组tabs的时候使用。每个页面对应的Fragment当用户可以访问的时候会一直存在内存中。

 

使用FragmentPagerAdapter至少需要实现以下两个方法:

    FragmentPagerAdapter adapter = new FragmentPagerAdapter(  

               getSupportFragmentManager()) {  

                //返回ViewPager页面的数量

                @Override  

                public int getCount() {  

                    return fragments.size();  

                }  

               //要显示的fragent对象。

                @Override  

                public Fragment getItem(int position) {  

                    return fragments.get(position);  

                }  

                }  

      

            };  

  • 补充  自定义viewPager的Tab导航标签
  1. 分析标签的结构

<?xml version="1.0" encoding="utf-8"?>

<!-- tab控件的布局 -->

<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:id="@+id/hsv_id"

    android:scrollbars="@null"

    >

    

    <!-- 最外层的LinearLayout 纵向 -->

    <LinearLayout

        android:layout_width="wrap_content"

        android:layout_height="match_parent"

        android:orientation="vertical">

        

        <!-- Tab项布局 横向 -->

        <LinearLayout

            android:id="@+id/ll_tab"

 android:layout_width="wrap_content"

            android:layout_height="0dp"

            android:layout_weight="9"

            android:orientation="horizontal"/>

        <View

         android:id="@+id/view_nav"

        android:layout_width="0dp"

        android:layout_height="0dp"

        android:layout_weight="1"

        android:background="#f00"/>

        

        <View

            android:layout_width="match_parent"

            android:layout_height="1dp"

            android:background="#f00"/>

        

    </LinearLayout>

 

</HorizontalScrollView>

  1. 测量每一个标签的宽度

    tv.getPaint().setFakeBoldText(true);//设置字体加粗效果

//调用一下组件的测量方法

tv.measure(0, 0);//通知系统对组件进行测量

tv.getMeasuredWidth();//获得标签的宽度

  1. 移动滑块的位置

 

  //计算滑块的宽度

        if (position == titleWidths.size()-1){

            slideWidth = titleWidths.get(position);

        }else {

            slideWidth =(int)(titleWidths.get(position)+

            (titleWidths.get(position+1)-titleWidths.get(position))

*positionOffset);

 

        }

 

//滑块位置

int slideMarginLeft = 0;

        for (int i = 0; i < position; i++)

        {

            slideMarginLeft += titleWidths.get(i);

        }

        slideMarginLeft+=titleWidths.get(position)*positionOffset;

        slidePrams.leftMargin = slideMarginLeft;

  • 补充   FragmentPagerAdapter 和 FragmentStatePagerAdapter 的区别:

 

FragmentPagerAdapter:只会销毁fragment的视图,fragment的对象被保留在了内存中,下次再创建该fragment时,直接从内存中获得该对象,如果页面较少,

并且不需要动态更新时,用这种适配器用户体验较好,开销较少

FragmentStatePagerAdapter:会直接销毁fragment对象,下次再使用该fragment时,重新创建新的对象。页面较多,并且需要动态更新的时候,需要使用该适配器。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值