安卓学习日志 Day09 — ViewPager

前提

Miwok 应用现在外观已经很美观惊艳!看起来已经创建完毕了,为何还要更改呢?

这在应用开发团队中是有可能发生的。已经构建了第 1 个版本的应用,然后团队决定重新设计并提供更好的用户体验。然后就开始构建第 2 个版本的应用!

作为开发者,需要掌握的重要技能是能够重构代码。在应用中保留相同的功能,但是外观上却看起来不同。在采用新的设计模式的时候,不能破坏任何现有的功能(例如,不能丢失图片或音频播放功能)。当破坏了某些功能,用户无法再像在之前的版本中那样执行某些任务的话,就称之为退步

为了确保我们没有破坏任何功能,我们可以一次完成一个小小的阶段。尽可能多次在设备上运行下应用。你肯定不希望花 5 天的时间编写出新的代码,然后发现应用不能在设备上运行了。

以下是新的设计模式。我们希望能在单词列表之间滑动。这样我们就不用再点按一次,才能打开单词列表。当我们启动应用后,就可以立即看到单词列表。

在这里插入图片描述

但在重构 Miwok 应用之前,将构建一个小型且具有单一的功能的应用,用于测试 新功能,同时了解下 ViewPager 在简单情形下是如何工作的。

在本文结束后,构建的应用应该与下面这个类似:

在这里插入图片描述

ViewPager

Viewpager是android开发的一个非常好的特性,它通过水平滑动屏幕来帮助用户从一个视图移动到另一个视图。

ViewPager 是一个布局管理器,它允许用户左右翻转数据页面。它主要出现在 Youtube、Snapchat 等应用中,用户在这些应用中左右切换切换到屏幕。使用的不是 Activity,而是 Fragment。当用户第一次启动应用程序时,它也用于引导用户通过应用程序。

ViewPager 在Android 中 使用片段 Fragment

实现 viewpager 的步骤:

  1. 将ViewPager小部件添加到XML布局(通常是 main_layout )。

  2. 通过扩展 FragmentPagerAdapter 或 FragmentStatePagerAdapter 类来创建适配器。

适配器填充Viewpager中的页面。PagerAdapter是由FragmentPagerAdapter和FragmentStatePagerAdapter扩展的基类。

FragmentPagerAdapter和FragmentStatePagerAdapter的区别:

FragmentStatePagerAdapter :只将屏幕上显示的当前片段保存在内存中。这是有效的内存,应该在具有动态片段的应用程序中使用。(碎片的数量是不固定的。)

FragmentPagerAdapter :当片段的数量固定时,应该使用这个适配器。应用程序有3个选项卡,在应用程序运行期间不会改变。

关于 ViewPager 的更多细节本文将不再解释,更多可以参考 文末 参考链接中的 相关文章。

示例编写

1、创建项目

创建一个新的项目在Android Studio从文件 ==> 新项目 ==> 选择 Empty Activity 以此来创建一个具有空模板的 Android项目。

最终,项目目录应该如下所示:

在这里插入图片描述

2、ViewPager 布局

ViewPager 的布局一共需要三个小部件,AppBarLayout 用于托管 TabLayout , TabLayout 负责显示页面标题。ViewPager 布局,将存放不同的片段。下图解释了要设置的重要参数,以使应用程序正常工作。

在这里插入图片描述

TabLayout 提供了一个水平布局来显示选项卡。如果使用 TabLayout,那么也使用 Fragment,因为 Fragment 是轻量级的,如果添加更多的 Fragment,应用程序可以在一个屏幕上有更多的功能。每当用户单击标签时,它将导致一个片段到另一个片段的切换。ViewPager用于在选项卡之间滑动。WhatsApp、Facebook等都是使用ViewPager进行 TabLayout的很好的例子。这就是 TabLayout的样子。

图片来自 https://www.geeksforgeeks.org/kotlin-android-tutorial/

TabLayout 中,需要添加 tabmode = "fixed" 参数,这将告诉android系统,在我们的应用程序中将有一个固定数量的标签。最终的 activity_main.xml 文件 如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:tabGravity="fill"
            app:tabMode="fixed" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

3、创建碎片

在 Android Studio 中创建碎片 Fragment ,File => New => Fragment => Fragment (Blank) => 填写恰当的 Fragment 名称 => Finish,创建步骤如下:

在这里插入图片描述

在本文中,将使用三个页面(Fragments),分别为 FragmentFirstFragmentSecondFragmentThird ,完成后的项目结构应该如下所示:

在这里插入图片描述

下面是 FragmentFirst.javaFragmentSecond.javaFragmentThird.java 中的代码:

FragmentFirst.java

package com.example.viewpagerdemo;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FragmentFirst extends Fragment {
    
    

    public FragmentFirst() {
    
    
        // required empty public constructor.
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return inflater.inflate(R.layout.fragment_first, container, false);
    }
}

FragmentSecond.java

package com.example.viewpagerdemo;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FragmentSecond extends Fragment {
    
    

    public FragmentSecond() {
    
    
        // required empty public constructor.
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return inflater.inflate(R.layout.fragment_second, container, false);
    }
}

FragmentThird.java

package com.example.viewpagerdemo;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FragmentThird extends Fragment {
    
    

    public FragmentThird() {
    
    
        // required empty public constructor.
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return inflater.inflate(R.layout.fragment_third, container, false);
    }
}

方法描述:

  • FragmentFirst(): 空构造函数(默认结构)
  • onCreateView( onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState): 该方法负责扩展(解析)各自的XML文件,并返回添加到 ViewPager 适配器的视图。
  • onCreate(Bundle SaveInstanceState): 此方法类似于 Activity 当中的 OnCreate() 方法。

设计页面XML文件。所有的片段XML布局都有相同的设计。有一个 TextView 在中心显示相应的 Fragment 的名称,这里使用的根容器是帧布局。

下面是布局文件 fragment_first.xmlfragment_second.xmlfragment_third.xml 中的代码。

fragment_first.xml 文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".FragmentFirst">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="First Fragment"
        android:textColor="@color/black"
        android:textSize="24sp" />
</FrameLayout>

下面是 fragment_second.xml 文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".FragmentSecond">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Second Fragment"
        android:textColor="@color/black"
        android:textSize="24sp" />
</FrameLayout>

下面是 fragment_third.xml 文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".FragmentThird">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Third Fragment"
        android:textColor="@color/black"
        android:textSize="24sp" />
</FrameLayout>

4、创建适配器

向项目结构中添加一个名为 ViewPaqerAdapter 的 java类。项目结构如下所示。

在这里插入图片描述

ViewPagerAdapter.java 文件的代码如下:

package com.example.viewpagerdemo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

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

public class ViewPagerAdapter extends FragmentPagerAdapter {
    
    

    private final List<Fragment> fragments = new ArrayList<>();
    private final List<String> fragmentTitle = new ArrayList<>();

    public ViewPagerAdapter(@NonNull FragmentManager fm) {
    
    
        super(fm);
    }

    public void add(Fragment fragment, String title) {
    
    
        fragments.add(fragment);
        fragmentTitle.add(title);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
    
    
        return fragments.get(position);
    }

    @Override
    public int getCount() {
    
    
        return fragments.size();
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
    
    
        return fragmentTitle.get(position);
    }
}

这个自定义的适配器有两个成员变量,fragmentsfragmentTitle 分别应用存储 碎片(Fragment 对象)和 每个对象的名称。

add(Fragment fragment, String title) 方法用于 向适配器添加一个 碎片以及该碎片的名称。

5、处理 MainActivity

在MainActivity中,我们需要执行以下步骤。

  1. 初始化 ViewPager、TabLayout和适配器。
  2. 在标题旁边加上页码(片段)
  3. 使用 setupWithiewPager 方法将 TabLayout 链接到Viewpager。

Syntax: TabLayout.setupWithiewPager(ViewPager pager).

Description: The tablayout with the viewpager. The titles of each pager now appears on the tablayout. The user can also navigate throught the fragments by clicking on the tabs.

Parameter:

Viewpager: Used to display the fragments.

下面是 MainActivity.java 文件的代码。

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import androidx.viewpager.widget.ViewPager;

import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {
    
    

    private ViewPagerAdapter viewPagerAdapter;
    private ViewPager viewPager;
    private TabLayout tabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = findViewById(R.id.viewpager);

        // setting up the adapter
        viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());

        // add the fragments
        viewPagerAdapter.add(new FragmentFirst(), "First");
        viewPagerAdapter.add(new FragmentSecond(), "Second");
        viewPagerAdapter.add(new FragmentThird(), "Third");

        // Set the adapter
        viewPager.setAdapter(viewPagerAdapter);

        // The Page (fragment) titles will be displayed in the
        // tabLayout hence we need to set the page viewer
        // we use the setupWithViewPager().
        tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);
    }
}
  1. 20 行,ViewPager 视图
  2. 23,初始化 ViewPagerAdapter 适配器,需要传入一个 FragmentManager 对象,这个对象从 getSupportFragmentManager() 方法获得
  3. 26 - 28,添加三个 Fragment 对象 给适配器,以及它们的名称
  4. 31 行,为 ViewPager 视图 绑定适配器
  5. 36 - 37 行,水平选项卡,用于显示 每个 碎片的标题

6、运行

最终运行效果如下:

在这里插入图片描述

总结

ViewPager 的运作方式是从 FragmentPagerAdapter 适配器那获取数据。

对我们来说,我们需要自定义该适配器,以便显示我们自己的 Fragment,因此我们需要使用 FragmentPagerAdapter 的子类。通过继承,我们免费获得了 FragmentPagerAdapter 的所有功能,并且可以在上面添加我们的自定义功能。我们创建一个 ViewPagerAdapter 类,并继承自 FragmentPagerAdapter 类。

当你在设备上启动该应用时,首先 ViewPager 会询问该适配器将有多少页面。对我们来说, 适配器会说有 3 个页面。请参阅 ViewPagerAdapter getCount() 方法。

为了让 ViewPager 能够显示第 0 页,ViewPager 会向适配器请求第 0 个 Fragment。 请参阅 ViewPagerAdapter getItem(int position) 方法。当用户向左 滑动时,我们移到第 1 页,表示 ViewPager 向适配器寻求位置 1 的 Fragment。当我们 转到第 2 页时,ViewPager 会向适配器寻求位置 2 的 Fragment。因此,根据用户滑到的 页面(亦成为位置),应用就会显示相应的 Fragment。

图片来自 https://www.geeksforgeeks.org/kotlin-android-tutorial/

参考

ViewPager | Android Developers

Create swipe views with tabs using ViewPager | Android …

Slide between fragments using ViewPager | Android Developers

Android ViewPager Example Tutorial - JournalDev

ViewPager Using Fragmentsbin Android with Example …

Android ViewPager | ViewPager Android Example - Technxt …

How to implement a TabLayout in Android using ViewPager and Fragments

ViewPager 示例 Github 链接

猜你喜欢

转载自blog.csdn.net/weixin_45075891/article/details/112740891