5.7. Использование ViewPager

5.7. Использование ViewPager

ViewPager выполняет роль слайдера для показа нескольких страниц между которыми можно перемещаться свайпами влево или вправо. В следующем примере показано использование ViewPager и разрабатывается приложение для смены фонового изображения устройства.

Для выполнения этого урока возьмите 6 изображений и измените их названия на aston_1.jpg, aston_2.jpg…. aston_6.jpg и скопируйте изображения в папку res/drawable.

Создайте новый проект с макетом Empty Activity, затем в файле MainActivity.java напишите следующий код:

public class MainActivity extends AppCompatActivity {
    ViewPager viewPager;
    MyPagerAdapter adapter;

    // Список изображений для показа
    List<Integer> list = new ArrayList<Integer>(Arrays.asList(R.drawable.aston_1, R.drawable.aston_2, R.drawable.aston_3, R.drawable.aston_4, R.drawable.aston_6));

    // Кнопка установки фона
    Button b;

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

        b = findViewById(R.id.setBg);

        viewPager = findViewById(R.id.pager);
        // Инициализация нового экземпляра MyPagerAdapter
        adapter = new MyPagerAdapter(getSupportFragmentManager());
        // Привязка адаптера к ViewPager
        viewPager.setAdapter(adapter);

        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Получение ID изображения текущей страницы
                int drawId = list.get(viewPager.getCurrentItem());
                // Получение ссылки к службе изменения обоев
                WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
                // Попытка установки нового обоя
                try {
                    wm.setResource(drawId);

                    // Вывод сообщения при замене обоя
                    Toast.makeText(getApplicationContext(), "Wallpaper changed successfully", Toast.LENGTH_SHORT).show();
                } catch (Exception e)
                {
                    // Вывод сообщения при сбое замены обоя
                    Toast.makeText(getApplicationContext(), "Error changing background", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
            }
        });
    }
    // Переопределения поведения кнопки Назад
    @Override
    public void onBackPressed() {
        // Если ViewPager показывает первую страницу тогда закрыть приложение
        // (нумерация начинается с 0 как в массивах поэтому под номером 0 находится первый элемент)
        if (viewPager.getCurrentItem() == 0)
        {
            super.onBackPressed();
            // Если показываются страницы больше первой тогда
        } else {
            // перейти к предыдущей странице
            viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
        }
    }

    class MyPagerAdapter extends FragmentStatePagerAdapter {
        // Список для хранения фрагментов
        List<GalleryFragment> flist = new ArrayList<>();

        // Конструктор класса, который получает в качестве аргумента FragmentManager
        public MyPagerAdapter(FragmentManager fm)
        {
            super(fm);
        }

        // Функция для возвращения текущего элемента
        @Override
        public GalleryFragment getItem(int position)
        {
            // Проверка запрошенного индекса и уже существующих фрагментов
            // в массиве, если запрашивается страница, которая ещё не создана
            // (когда индекс страницы больше длины массива -1), тогда инициализировать новый фрагмент
            if(position > flist.size() - 1)
            {
                // Если страница запрашивается в первый раз
                // инициализировать новый фрагмент и ссылку добавить в массив flist
                GalleryFragment gf = new GalleryFragment();
                // Инициализировать новый объект класса Bundle
                // и добавить в него значение ID изображения для этой страницы с ключом image
                Bundle b = new Bundle();
                b.putInt("image", list.get(position));
                // отправить аргументы фрагменту для обработки
                gf.setArguments(b);
                // Возвратить ссылку на фрагмент
                return gf;
            } else {
                // Если страница запрашивается в последующие разы вернуть
                // ссылку к уже сущетсвующему фрагменту
                return flist.get(position);
            }
        }

        // Служит для возвращения количества элементов в ViewPager
        @Override
        public int getCount() {
            return list.size();
        }
    }
}

Нажмите правой кнопкой мыши на папку с названием пакета приложения в моём случае он называется company.my.lesson11wallpaperchanger, выберите New -> Java Class. В поле название класса введите GalleryFragemnt, а в поле Superclass введите Fragment и из предложенных вариантов выберите androidx.fragment.app.Fragment

Иллюстрация №0. Напишите описание

Затем код файла GalleryFragment.java измените так:

public class GalleryFragment extends Fragment {
    // Fragment в отличии от Activity инициализируется через функцию
    // onCreateView, которая возвращает View данного фрагмента
    // возвращаемое View это главный контейнер (ImageView в файле макета в данном случае)
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
    {
        // Привязка макета к фрагменту
        View v = inflater.inflate(R.layout.screen_slide, parent, false);
        ImageView imageView = v.findViewById(R.id.content);
        // Установка изображения виджету ImageView, ID которого получени через аргументы с ключом image
        imageView.setImageDrawable(getResources().getDrawable(getArguments().getInt("image")));
        // Возвращение корневого (первого) элемента для показа
        return v;
    }
}

Измените код файла activity_main.xml так:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <androidx.viewpager.widget.ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/pager"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/setBg"
        android:text="Set Background"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="16dp"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

В папке layout нажмите правой кнопкой мыши и выберите New -> Layout Resource File, в поле название введите screen_slide.xml, а в поле Root element – Image View и измените код так:

<?xml version="1.0" encoding="utf-8"?>
<!--Макет для страниц-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/content"
    android:scaleType="fitCenter"
    android:src="@drawable/aston_1">
</ImageView>

Откройте файл app/manifest/AndroidManifest.xml, в этом файле необходимо добавить разрешение для смены фона, добавьте следующий код между тегом manifest и application:

<uses-permission android:name="android.permission.SET_WALLPAPER" />

Приложение для смены фонового изображения устройства готово. Запустите и протестируйте.