ViewPager和ViewPager+Fragment联合使用方法精炼详解


一、前期基础知识储备
使用了ViewPager, PagerSlidingTabStrip, SwipeRefreshLayout模仿Douban客户端的下拉刷新以及滑动的效果。

ViewPager—视图滑动切换工具——通过手势滑动可以完成View的切换,一般是用来做APP 的引导页或者实现图片轮播——意味着ViewPager中经常放的东西有两个:①图片,实现图片轮播器;②View视图,实现View 的切换,如应用启动页面。

ViewPager就是一个简单的页面切换组件,我们可以往里面填充多个View,然后我们可以左右滑动,从而切换不同的View。和前面学的ListView,GridView一样,我们也需要一个Adapter (适配器)将我们的View和ViewPager进行绑定,而ViewPager则有一个特定的Adapter—— PagerAdapter!另外,Google官方是建议我们使用Fragment来填充ViewPager的,这样 可以更加方便的生成每个Page,以及管理每个Page的生命周期!给我们提供了两个Fragment 专用的Adapter:FragmentPageAdapter(页面少+简单)和FragmentStatePagerAdapter(页面多+复杂)。

二、上代码,简单实现一个ViewPager
第一步:在主布局文件中添加ViewPager控件;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.douban.MainActivity">
 
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpage"
        android:layout_gravity="center"
        android:layout_weight="1.0"
        android:flipInterval="30"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:persistentDrawingCache="animation"/>
</RelativeLayout>


第二步:创建三个Itemzi布局,用于放置View,比如图片,本例中放入一个文本控件

<?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:background="#f4ff55"
    android:gravity="center"
    android:orientation="vertical">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个Page"
        android:textColor="#000000"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>


由于一样,代码就不重复贴了

第三步:创建适配器类,在里面实现ViewPager的四个方法;

pagerAdapter = new PagerAdapter() {
            @Override
            public int getCount() {
                return viewList.size();
            }
 
            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }
 
 
            //移除当前容器上的布局文件(切换为其他页面)
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView(viewList.get(position));
            }
 
            //为当前容器添加布局文件(即想要显示的布局文件)
            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                container.addView(viewList.get(position));
                return viewList.get(position);
            }
        };


getCount():获得viewpager中有多少个view;

destroyItem():移除一个给定位置的页面。适配器有责任从容器中删除这个视图;

instantiateItem(): ①将给定位置的view添加到ViewGroup(容器)中,创建并显示出来;

isViewFromObject(): 判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,对应的表示同一个View),通常我们直接写 return view == object!

第四步:Activity代码中绑定适配器和初始化View数据;

public class MainActivity extends AppCompatActivity {
 
    private View view1, view2,view3;
    private ViewPager viewPager;
    private PagerAdapter pagerAdapter;
 
    private List<View> viewList = new ArrayList<>();
    //创建一个ArrayList用来保存要切换的View
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = (ViewPager) findViewById(R.id.viewpage);
        LayoutInflater inflater = getLayoutInflater();
 
        view1 = inflater.inflate(R.layout.view_one, null);
        view2 = inflater.inflate(R.layout.view_two, null);
        view3 = inflater.inflate(R.layout.view_three, null);
        viewList.add(view1);
        viewList.add(view2);
        viewList.add(view3);
        //将三个布局文件放进ArrayList中
                //将 pagerAdapter与 viewPager绑定
        viewPager.setAdapter(pagerAdapter);
    }
}


小结:通过以上四步,我们就简单地实现了一个ViewPager的使用。通常我们利用这种ViewPager的实现方式通常是用于创建一个图片轮播器。

延伸1:为ViewPager指定默认页,开启应用时自动显示的即为默认页,不会出现跳转动画。

private void setDefaultItem(int position){
       // mViewPager 是布局中ViewPager的实例
        try {
            Class c = Class.forName("android.support.v4.view.ViewPager");
            Field field =c.getDeclaredField("mCurItem");
            field.setAccessible(true);
            field.setInt(mViewPager, position);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        mAdapetr.notifyDataSetChanged();
 
        mViewPager.setCurrentItem(position);
    }


// 使用时 在onCreate()中调用,注意写在ViewPager绑定adapter之后,传入需要跳转的页面int值即可
延伸2:每次ViewPager展示页面不仅仅当前页,可以看到上一页和下一页的边缘部分,如博客中的第一张图

 

  <!--android:paddingLeft="@dimen/card_padding"
        android:paddingRight="@dimen/card_padding"
        原来如此,使用ViewPager的卡片视图可以一次看到几张卡片
        关键是设置了ViewPager的padding属性
        ViewGroup容器控件 设置padding属性的作用?-->
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="330dp"
        android:layout_gravity="bottom"
        android:clipToPadding="false"
        android:overScrollMode="never"
        android:background="@color/colorAccent"
        android:paddingBottom="30dp"
        android:paddingEnd="30dp"
        android:paddingStart="30dp" />


不需要Java代码中进行处理,在XML布局中ViewPager中添加padding属性即可。

————————————————————我是分隔线————————————————————

下面,我们来简单实现一次ViewPager和Fragment的联合使用。使用之前首先我们首先要分析两个关键逻辑:

①如何实现用户点击菜单栏,然后显示对应的页面?

②如何实现用户滑动ViewPager,对应的菜单栏也发生改变?

本例中实现的方式都是采用了监听点击事件的方式来实现的。

第一步:创建三个碎片的布局,用于和碎片绑定,去替换单独的Item子布局;

<?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:background="#FFBA55"
    android:gravity="center"
    android:orientation="vertical">
 
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个Page"
        android:textColor="#000000"
        android:textSize="18sp"
        android:textStyle="bold" />
</LinearLayout>


由于是重复代码,这里就不全贴了。

第二步:创建三个碎片类,用于装载碎片的布局;

public class OneFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.view_one, null);
        return view;
    }
}


由于是重复代码,这里就不全贴了。

第三步:创建主布局文件,这里放入三个文本控件和一个ViewPager,前者用于实现菜单栏的效果,后者用于实现视图替换的效果。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.administrator.douban.MainActivity">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
 
        <TextView
            android:id="@+id/tv_item_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="菜单一" />
 
        <TextView
            android:id="@+id/tv_item_two"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="菜单二" />
 
        <TextView
            android:id="@+id/tv_item_three"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="菜单三" />
    </LinearLayout>
 
    <android.support.v4.view.ViewPager
        android:id="@+id/myViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />
 
</LinearLayout>


第四步:创建适配器——核心步骤,这里使用的是专属的适配器实现;

public class TabFragmentPagerAdapter extends FragmentPagerAdapter {
    private FragmentManager mfragmentManager;
    private List<Fragment> mlist;
 
    //这是一段构造器,我没写的时候,第一次代码是报错的,在我做了下面这个构造器之后,没有报错!!!
    public TabFragmentPagerAdapter(FragmentManager fm, List<Fragment> list) {
        super(fm);
        this.mlist = list;
    }
    //显示第几个页面
    @Override
    public Fragment getItem(int position) {
        return mlist.get(position);
    }
    //一共有几个页面,注意,使用Fragment特有的构造器时,和ViewPager的原生构造器的方法不同
    @Override
    public int getCount() {
        return mlist.size();
    }
}


第五步:创建主Activity代码,在这里做了三件事:①初始化碎片数据;②为ViewPager绑定适配器;③为菜单栏和View写入点击监听事件

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
 
    private TextView tv_item_one;
    private TextView tv_item_two;
    private TextView tv_item_three;
    private ViewPager myViewPager;
    private List<Fragment> list;
    private TabFragmentPagerAdapter adapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InitView();
 
        // 设置菜单栏的点击事件
        tv_item_one.setOnClickListener(this);
        tv_item_two.setOnClickListener(this);
        tv_item_three.setOnClickListener(this);
        myViewPager.setOnPageChangeListener(new MyPagerChangeListener());
 
        //把Fragment添加到List集合里面
        list = new ArrayList<>();
        list.add(new OneFragment());
        list.add(new TwoFragment());
        list.add(new ThreeFragment());
        adapter = new TabFragmentPagerAdapter(getSupportFragmentManager(), list);
        myViewPager.setAdapter(adapter);
        myViewPager.setCurrentItem(0);  //初始化显示第一个页面
        tv_item_one.setBackgroundColor(Color.RED);//被选中就为红色
    }
 
    private void InitView() {
        tv_item_one = (TextView) findViewById(R.id.tv_item_one);
        tv_item_two = (TextView) findViewById(R.id.tv_item_two);
        tv_item_three = (TextView) findViewById(R.id.tv_item_three);
        myViewPager = (ViewPager) findViewById(R.id.myViewPager);
    }
    //第一次设置点击监听事件,为菜单栏设置监听事件,监听的对象是页面的滑动
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_item_one:
                myViewPager.setCurrentItem(0);
                tv_item_one.setBackgroundColor(Color.RED);
                tv_item_two.setBackgroundColor(Color.WHITE);
                tv_item_three.setBackgroundColor(Color.WHITE);
                break;
            case R.id.tv_item_two:
                myViewPager.setCurrentItem(1);
                tv_item_one.setBackgroundColor(Color.WHITE);
                tv_item_two.setBackgroundColor(Color.RED);
                tv_item_three.setBackgroundColor(Color.WHITE);
                break;
            case R.id.tv_item_three:
                myViewPager.setCurrentItem(2);
                tv_item_one.setBackgroundColor(Color.WHITE);
                tv_item_two.setBackgroundColor(Color.WHITE);
                tv_item_three.setBackgroundColor(Color.RED);
                break;
        }
    }
    //第二次设置点击监听事件,为ViewPager设置监听事件,用于实现菜单栏的样式变化
    private class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 
        }
 
        @Override
        public void onPageSelected(int position) {
            switch (position) {
                case 0:
                    tv_item_one.setBackgroundColor(Color.RED);
                    tv_item_two.setBackgroundColor(Color.WHITE);
                    tv_item_three.setBackgroundColor(Color.WHITE);
                    break;
                case 1:
                    tv_item_one.setBackgroundColor(Color.WHITE);
                    tv_item_two.setBackgroundColor(Color.RED);
                    tv_item_three.setBackgroundColor(Color.WHITE);
                    break;
                case 2:
                    tv_item_one.setBackgroundColor(Color.WHITE);
                    tv_item_two.setBackgroundColor(Color.WHITE);
                    tv_item_three.setBackgroundColor(Color.RED);
                    break;
            }
        }
 
        @Override
        public void onPageScrollStateChanged(int state) {
 
        }
    }
}


运行效果如下:

终极:使用新的系统控件BottomNavigationBar搭配ViewPager实现导航效果
效果如图:

添加依赖:

implementation 'com.ashokvarma.android:bottom-navigation-bar:2.1.0' 
上面是BottomNavigationBar最新的依赖库。
Activity代码部分:

public class EndGuideActivity extends AppCompatActivity {
    private ViewPager mVpHome;
    private BottomNavigationBar mBottomNavigationBar;
    private ArrayList<Fragment> mFragmentList = new ArrayList<>();
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_end_guide);
        hideStatusBar(); //隐藏状态栏
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
            actionBar.hide(); //隐藏标题栏
        }
        mVpHome = (ViewPager) findViewById(R.id.vp_home);
        mBottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
        mBottomNavigationBar.addItem(new BottomNavigationItem(R.drawable.ic_favorite, "One"))
                .addItem(new BottomNavigationItem(R.drawable.ic_gavel, "Two"))
                .addItem(new BottomNavigationItem(R.drawable.ic_grade, "Three"))
                .addItem(new BottomNavigationItem(R.drawable.ic_group_work, "Four"))
                .addItem(new BottomNavigationItem(R.drawable.ic_favorite, "Five"))
                .addItem(new BottomNavigationItem(R.drawable.ic_gavel, "Six"))
                .initialise();
        mBottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener() {
            @Override
            public void onTabSelected(int position) {
                mVpHome.setCurrentItem(position); //下面动 上面跟着动走的是这个方法
            }
 
            @Override
            public void onTabUnselected(int position) {
 
            }
 
            @Override
            public void onTabReselected(int position) {
 
            }
        });
 
        mFragmentList.add(new ImageFragment());
        mFragmentList.add(new SimpleFragment());
        mFragmentList.add(new SimpleFragment());
        mFragmentList.add(new SimpleFragment());
        mFragmentList.add(new SimpleFragment());
        mFragmentList.add(new SimpleFragment());
 
        mVpHome.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 
            }
 
            @Override
            public void onPageSelected(int position) {
                mBottomNavigationBar.selectTab(position);//上面移动 下面跟着动走的是这个方法
                switch (position) {
                    case 0:
                        break;
                    default:
                        //随机取颜色
                        Random random = new Random();
                        int color = 0xff000000 | random.nextInt(0xffffff);
                        if (mFragmentList.get(position) instanceof SimpleFragment) {
                            ((SimpleFragment) mFragmentList.get(position)).setTvTitleBackgroundColor(color);
                        }
                        break;
                }
            }
 
            @Override
            public void onPageScrollStateChanged(int state) {
 
            }
        });
        mVpHome.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return mFragmentList.get(position);
            }
 
            @Override
            public int getCount() {
                return mFragmentList.size();
            }
 
        });
    }
 
    /*
    * 隐藏状态栏
    * */
    public void hideStatusBar() {
        if (Build.VERSION.SDK_INT < 30) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {
            View decorView = getWindow().getDecorView();
            int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(uiOptions);
        }
    }
}


XML布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#fff">
 
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_home"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"/>
 
    <com.ashokvarma.bottomnavigation.BottomNavigationBar
        android:id="@+id/bottom_navigation_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:bnbActiveColor="#fff"
        app:bnbBackgroundColor="@color/colorPrimary"
        app:bnbBackgroundStyle="background_style_static"/>
</LinearLayout>


两个Fagment的代码如下:

// 纯色Activity
public class SimpleFragment extends Fragment {
    private TextView mTvTitle;
    private View mFakeStatusBar;
 
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragement_simple, container, false);
    }
 
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mTvTitle = (TextView) view.findViewById(R.id.tv_title);
        mFakeStatusBar = view.findViewById(R.id.fake_status_bar);
    }
 
    public void setTvTitleBackgroundColor(@ColorInt int color) {
        mTvTitle.setBackgroundColor(color);
        mFakeStatusBar.setBackgroundColor(color);
    }
}
// 图片Activity
public class ImageFragment extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragement_image, container, false);
    }
}


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">
 
    <View
        android:id="@+id/fake_status_bar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"/>
 
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="@string/app_name"
        android:textColor="#fff"
        android:textSize="24sp"/>
</LinearLayout>
<?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">
 
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:src="@mipmap/ic_launcher_round"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="56dp"
        android:text="This is a fragment."
        android:textSize="22sp"/>
 
</LinearLayout>


总结:单独使用ViewPager比较简单,把ViewPager看成是普通的容器控件,是一个大方块,里面实现好了滑动显示逻辑,我们要做的就是做好适配器,然后往适配器里面加东西,比如三张图片,三个TextView——使用起来是比较简单的。

使用ViewPager+Fragment和单独使用ViewPager也比较类似,只是把单个的View布局文件换成了碎片。而构造器用的也是Fragment专属的构造器。需要注意的一点就是,为了实现①如何实现用户点击菜单栏,然后显示对应的页面?②如何实现用户滑动ViewPager,对应的菜单栏也发生改变?这两个关键逻辑,需要分别为菜单栏和ViewPager注册点击监听事件。
————————————————

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现 ViewPager2+TabLayout+Fragment 实现页面切换,需要以下步骤: 1. 在 XML 布局文件中定义 ViewPager2 和 TabLayout,并将它们嵌套在一个父布局中。 ```xml <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable" app:tabGravity="center"/> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@id/tab_layout" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> ``` 2. 创建 Fragment,并实现 ViewPager2 的适配器。 ```kotlin class MyFragmentAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) { private val fragmentList = listOf( FirstFragment(), SecondFragment(), ThirdFragment() ) override fun getItemCount() = fragmentList.size override fun createFragment(position: Int) = fragmentList[position] } ``` 3. 在 Activity 或 Fragment 中,初始化 ViewPager2 和 TabLayout,并将适配器设置给 ViewPager2。 ```kotlin val viewPager: ViewPager2 = findViewById(R.id.view_pager) val tabLayout: TabLayout = findViewById(R.id.tab_layout) val adapter = MyFragmentAdapter(this) viewPager.adapter = adapter TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = "Tab ${position + 1}" }.attach() ``` 这样就可以实现 ViewPager2+TabLayout+Fragment 实现页面切换了。注意,TabLayoutMediator 是用来关联 TabLayout 和 ViewPager2 的,它的第一个参数是 TabLayout,第二个参数是 ViewPager2,第三个参数是一个回调函数,用来设置 TabLayout 的标签文本。在最后一行调用 attach() 方法即可完成关联。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值