ViewPager dengan batas halaman sebelumnya dan berikutnya

144

Saya mendesain tampilan dengan beberapa halaman. Saya ingin tepi halaman sebelumnya dan berikutnya ditampilkan seperti di bawah ini dan menerapkan sapuan 2 jari untuk beralih di antara halaman.

masukkan deskripsi gambar di sini

Saya mencoba menggunakan ViewPagerdengan margin halaman negatif seperti yang disarankan di sini, tetapi itu hanya menunjukkan salah satu ujung di layar, tidak keduanya secara bersamaan.

Atau, apakah ada cara saya dapat memposisikan bagian dari tampilan saya di luar layar dan kemudian menghidupkannya sehingga memberikan ViewPagerefek tipe.

Bagaimana saya harus melakukannya? Terima kasih!

Gaurav Arora
sumber
"Hanya menunjukkan salah satu ujung di layar, bukan keduanya secara bersamaan." Apakah Anda di halaman 0 dan Anda hanya melihat bagian dari halaman 1? Mungkin Anda perlu menggunakan pager melingkar, contoh dan kemudian atur halaman Anda selalu ke posisi "tengah". Lihat postingan ini dan komentarnya: stackoverflow.com/a/8304474/1851478
logray

Jawaban:

100

Mengutip diri sendiri dari posting blog tentang hal ini :

Pendekatan ketiga datang dari Dave Smith, rekan penulis buku Android Recipes yang dianggap baik. Dia pergi ke arah yang sangat berbeda, menggunakan wadah khusus yang memungkinkan anak-anak terpotong untuk menunjukkan lebih dari satu halaman sekaligus.

Nya diterbitkan kode contoh menunjukkan semuanya dalam tindakan. Wadahnya ( com.example.pagercontainer.PagerContainer) membungkus ViewPagerdan memanggilnya setClipChildren(false);sendiri, jadi meskipun ViewPagerterfokus pada satu halaman yang dipilih, halaman lain yang memiliki koordinat di luar ViewPagerbatas masih terlihat, asalkan sesuai dengan PagerContainer. Dengan ukuran yang ViewPagerlebih kecil dari yang PagerContainer, ViewPagerukuran kaleng halaman ke ukuran itu, meninggalkan ruang untuk halaman lain untuk dilihat. PagerContainerNamun, perlu sedikit membantu dengan acara sentuh, karena ViewPagerhanya akan menangani acara gesek pada batas yang terlihat sendiri, mengabaikan halaman apa pun yang terlihat di samping.

masukkan deskripsi gambar di sini

CommonsWare
sumber
1
dengan menggunakan ini, saya dapat menunjukkan bagian dari halaman sebelumnya dan berikutnya seperti yang ditunjukkan pada gambar di atas, tapi sekarang saya tidak ingin menunjukkan tepi tajam pada gambar. Saya ingin mereka kabur ke tepi .. tolong bantu saya bagaimana bisa saya menggunakan z-index untuk mencapai hal yang sama
Shruti
2
@Shruti - cukup tambahkan gambar hamparan dengan efek yang Anda inginkan
Daniel L.
2
Saya melakukan hal yang sama tetapi menonaktifkan efek over-scroll untuk item terakhir. Adakah petunjuk tentang itu?
Swayam
1
@ CommonsWare: Pak, saya mencoba solusi Anda! Itu bekerja dengan cukup baik. Overcroll ada di sana. Satu-satunya masalah sekarang adalah bahwa kartu berikutnya menunjukkan, tetapi bukan kartu sebelumnya. Yaitu, jika saya di halaman 2, saya bisa melihat halaman 3 mengintip keluar, tetapi bukan halaman 1. Di mana saya bisa salah?
Swayam
2
@Swayam: Saya tidak tahu.
CommonsWare
110

Saya punya solusi serupa:

Pada viewpager atur padding kiri dan kanan, mis. 20dp. Juga mengatur margin halaman pada viewpager, misalnya setengah dari pager padding. Dan jangan lupa untuk menonaktifkan clip padding.

tilePager.setPadding(defaultGap, 0, defaultGap, 0);
tilePager.setClipToPadding(false);
tilePager.setPageMargin(halfGap);
Thomas R.
sumber
2
Solusi bagus disediakan.
akash89
cara termudah dan terbaik
HannahCarney
Ini adalah jawaban beast yes beast untuk mempertimbangkan nilai penamaan xd
silentsudo
1
catatan: ini tidak akan bekerja dengan transformator pager tampilan kustom
voytez
@voytez ada solusi untuk transformator?
Alex
76
  1. Atur padding kiri dan kanan untuk seluruh tampilan item. Contoh xml (page_item.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"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"/>
    
    <TextView
        android:id="@+id/text1"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </LinearLayout>
  2. Kemudian setel margin halaman negatif PageViewmenjadi sama dengan 2 * (tampilan sebelumnya)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
  3. Pilihan. Atur nol padding kiri untuk item pertama dan nol padding kanan untuk item terakhir untuk menyembunyikan tepi kosong. Anda dapat melakukan ini di PageAdapteratau Pagekelas fragmen.

SergeyA
sumber
@Sergey, saya tidak bisa melakukan ini dengan solusi Anda, bisakah Anda memposting contoh? thx
Marckaraujo
12
hanya menambahkan catatan: dengan solusi ini ketika Anda meluncur dari halaman 1 ke halaman 2, halaman 3 tidak ada dalam memori, sehingga akan muncul dengan penundaan. untuk memperbaikinya tambahkan saja - yourViewPager.setOffscreenPageLimit (2);
José Barbosa
Saya melakukan hal yang sama tetapi menonaktifkan efek over-scroll untuk item terakhir. Adakah petunjuk tentang itu?
Swayam
Sepertinya saya tidak bisa mendapatkan ini berfungsi baik ... margin tampaknya ditampilkan secara acak jika saya menggunakan gambar w / skala yang diatur ke tengah memotong. Adakah yang punya contoh kode kerja yang bisa mereka bagikan?
kenyee
2
Bagaimana cara menyentuh item pertama dan terakhir? Dengan memeriksa indeks halaman di OnPageListener?
Hardik9850
47

Untuk menampilkan pratinjau halaman kiri dan kanan, atur dua nilai berikut

viewpager.setClipToPadding(false)
viewpager.setPadding(left,0,right,0)

Jika Anda membutuhkan ruang antara dua halaman di viewpager kemudian tambahkan viewpager.setPageMargin (int)

Android ViewPager - Tampilkan pratinjau halaman di kiri dan kanan

molu2008
sumber
3
Ini harus jawaban yang benar. Saya pikir mungkin ini tidak bekerja di versi viewpager sebelumnya tetapi berfungsi sekarang.
Greg Ennis
Ini menambahkan margin yang sama di sisi kiri halaman pertama dan kanan juga. Perbaikan apa pun
Umesh Aawte
1
Jawaban singkat dan lebih jelas.
Imran Ahmed
10

jika seseorang masih mencari solusi, saya telah mengkustomisasi ViewPage untuk mencapainya tanpa menggunakan margin negatif, temukan contoh proyek di sini https://github.com/44kksharma/Android-ViewPager-Carousel-UI seharusnya berfungsi dalam banyak kasus, tetapi Anda masih dapat mendefinisikan margin halaman dengan mPager.setPageMargin(margin in pixel);

44kk sharma
sumber
1

Unduh kode sumber dari sini ( ViewPager dengan batas halaman sebelumnya dan berikutnya )

MainActivity.java

package com.deepshikha.viewpager;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.ViewGroup;

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

public class MainActivity extends FragmentActivity {

    ViewPager pager;
    MyPageAdapter obj_adapter;
    String str_device;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();


    }

    private void init() {
        pager = (ViewPager) findViewById(R.id.viewpager);
        differentDensityAndScreenSize(getApplicationContext());
        List<Fragment> fragments = getFragments();
        pager.setAdapter(obj_adapter);
        pager.setClipToPadding(false);


        if (str_device.equals("normal-hdpi")){
            pager.setPadding(160, 0, 160, 0);
        }else if (str_device.equals("normal-mdpi")){
            pager.setPadding(160, 0, 160, 0);
        }else if (str_device.equals("normal-xhdpi")){
            pager.setPadding(160, 0, 160, 0);
        }else if (str_device.equals("normal-xxhdpi")){
            pager.setPadding(180, 0, 180, 0);
        }else if (str_device.equals("normal-xxxhdpi")){
            pager.setPadding(180, 0, 180, 0);
        }else if (str_device.equals("normal-unknown")){
            pager.setPadding(160, 0, 160, 0);
        }else {

        }

        obj_adapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        pager.setPageTransformer(true, new ExpandingViewPagerTransformer());
        pager.setAdapter(obj_adapter);
    }

    class MyPageAdapter extends FragmentPagerAdapter {

        private List<Fragment> fragments;

        public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {

            super(fm);

            this.fragments = fragments;

        }

        @Override

        public Fragment getItem(int position) {

            return this.fragments.get(position);

        }

        @Override

        public int getCount() {

            return this.fragments.size();

        }

    }

    private List<Fragment> getFragments() {

        List<Fragment> fList = new ArrayList<Fragment>();

        fList.add(MyFragment.newInstance("Fragment 1",R.drawable.imags));
        fList.add(MyFragment.newInstance("Fragment 2",R.drawable.image1));
        fList.add(MyFragment.newInstance("Fragment 3",R.drawable.image2));
        fList.add(MyFragment.newInstance("Fragment 4",R.drawable.image3));
        fList.add(MyFragment.newInstance("Fragment 5",R.drawable.image4));

        return fList;

    }

    public int differentDensityAndScreenSize(Context context) {
        int value = 20;
        String str = "";
        if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
            switch (context.getResources().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "small-ldpi";
                    // Log.e("small 1","small-ldpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "small-mdpi";
                    // Log.e("small 1","small-mdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    str = "small-hdpi";
                    // Log.e("small 1","small-hdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    str = "small-xhdpi";
                    // Log.e("small 1","small-xhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    str = "small-xxhdpi";
                    // Log.e("small 1","small-xxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    str = "small-xxxhdpi";
                    //Log.e("small 1","small-xxxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    str = "small-tvdpi";
                    // Log.e("small 1","small-tvdpi");
                    value = 20;
                    break;
                default:
                    str = "small-unknown";
                    value = 20;
                    break;
            }

        } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
            switch (context.getResources().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "normal-ldpi";
                    // Log.e("normal-ldpi 1","normal-ldpi");
                    str_device = "normal-ldpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("normal-mdpi 1","normal-mdpi");
                    str = "normal-mdpi";
                    value = 82;
                    str_device = "normal-mdpi";
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    // Log.e("normal-hdpi 1","normal-hdpi");
                    str = "normal-hdpi";
                    str_device = "normal-hdpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    //Log.e("normal-xhdpi 1","normal-xhdpi");
                    str = "normal-xhdpi";
                    str_device = "normal-xhdpi";
                    value = 90;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("normal-xxhdpi 1","normal-xxhdpi");
                    str = "normal-xxhdpi";
                    str_device = "normal-xxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    //Log.e("normal-xxxhdpi","normal-xxxhdpi");
                    str = "normal-xxxhdpi";
                    str_device = "normal-xxxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("DENSITY_TV 1","normal-mdpi");
                    str = "normal-tvdpi";
                    str_device = "normal-tvmdpi";
                    value = 96;
                    break;
                default:
                    // Log.e("normal-unknown","normal-unknown");
                    str = "normal-unknown";
                    str_device = "normal-unknown";
                    value = 82;
                    break;
            }
        } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
            switch (context.getResources().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    str = "large-ldpi";
                    // Log.e("large-ldpi 1","normal-ldpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "large-mdpi";
                    //Log.e("large-ldpi 1","normal-mdpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "large-hdpi";
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-xhdpi");
                    str = "large-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    //Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "large-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "large-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("large-ldpi 1","normal-tvdpi");
                    str = "large-tvdpi";
                    value = 125;
                    break;
                default:
                    str = "large-unknown";
                    value = 78;
                    break;
            }

        } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
            switch (context.getResources().getDisplayMetrics().densityDpi) {
                case DisplayMetrics.DENSITY_LOW:
                    // Log.e("large-ldpi 1","normal-ldpi");
                    str = "xlarge-ldpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("large-ldpi 1","normal-mdpi");
                    str = "xlarge-mdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-hdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "xlarge-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "xlarge-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("large-ldpi 1","normal-tvdpi");
                    str = "xlarge-tvdpi";
                    value = 125;
                    break;
                default:
                    str = "xlarge-unknown";
                    value = 125;
                    break;
            }
        }

        return value;
    }
}
Deepshikha Puri
sumber
1
Kode ini tidak berfungsi sebagaimana mestinya, ini menunjukkan halaman sisi kiri sedikit lebih besar dari sisi kanan
Chirag Joshi
1

Beberapa waktu yang lalu saya memerlukan fitur tersebut dan menyiapkan perpustakaan kecil yang digunakan RecyclerViewdengan PagerSnapHelper (ditambahkan dalam versi 25.1.0 dari perpustakaan dukungan v7) alih-alih klasik ViewPager:

MetalRecyclerPagerView - Anda dapat menemukan semua kode beserta contoh di sana.

Terutama terdiri dari file kelas tunggal: MetalRecyclerViewPager.java (dan dua xml: attrs.xml dan ids.xml ).

Semoga ini bisa membantu seseorang :)

Alexander Bilchuk
sumber