Android ViewPager - แสดงตัวอย่างของหน้าทางซ้ายและขวา


108

ฉันใช้ ViewPagerAndroid สิ่งที่ฉันต้องการทำคือการแสดงตัวอย่างของหน้าทั้งทางซ้ายและทางขวา ฉันเคยเห็นว่าฉันสามารถใช้ลบpageMarginเพื่อแสดงตัวอย่างทางด้านขวาได้ที่ไหน

setPageMargin(-100);

ยังมีอีกไหมที่ฉันสามารถแสดงตัวอย่างด้านซ้ายได้ด้วย? โดยพื้นฐานแล้วมันคล้ายกับวิดเจ็ตแกลเลอรีที่ฉันกำลังมองหา


คำถามที่ดี! ฉันเพิ่งตรวจสอบแหล่งที่มาและฉันรู้สึกว่าไม่มีวิธีใดดีไปกว่านี้หากคุณไม่ต้องการแก้ไขโค้ด src ไม่setPageMargin(-100)ทำงานถูกต้องหรือไม่
Macarse

GalleryView จะทำงานได้ดีขึ้นเว้นแต่ว่าคุณกำลังใช้ ViewPger กับส่วนย่อย
Ali AlNoaimi

ฉันสามารถทำได้โดยใช้มุมมองแกลเลอรี เช่นเดียวกับ viewpager แต่อย่างใด ไม่รู้ว่าทำไมแกลเลอรีจึงเลิกใช้งาน
WillingLearner

คำถามนี้ได้รับการกล่าวถึงอย่างกว้างขวางใน [โพสต์ที่นี่] [1] [1]: stackoverflow.com/questions/13914609/…
Ben Pearson

ฉันใช้ Vierpager กับชิ้นส่วนดังนั้นฉันสามารถใช้แนวทางเดียวกันได้หรือไม่
asliyanage

คำตอบ:


206

หากต้องการแสดงตัวอย่างของหน้าซ้ายและขวาให้ตั้งค่าสองค่าต่อไปนี้

  1. viewpager.setClipToPadding(false);
  2. viewpager.setPadding(left,0,right,0);

หากคุณต้องการช่องว่างระหว่างสองเพจใน viewpager ให้เพิ่ม

viewpager.setPageMargin(int);

2
ใช่ฉันเห็นด้วยกับคุณ Jiju Induchoodan .. สำหรับข้อมูลเพิ่มเติมโปรดดูblog.neteril.org/blog/2013/10/14/…และstackoverflow.com/questions/13914609/…
Sripathi

เจ๋งมันง่ายมาก :) สามารถปรับขนาดตัวอย่างเป็นขนาดขวาและซ้ายบนหน้าสลับของเพจเจอร์มุมมองได้หรือไม่? ตัวอย่างเช่น - หากแฟรกเมนต์ไม่อยู่ในโฟกัส - สเกลจะเป็น ~ 0.8 แต่เมื่อเราลากไปที่กึ่งกลาง - สเกลจะเพิ่มเป็น 1 และแฟรกเมนต์ก่อนหน้าจากมุมมองกึ่งกลางจะเปลี่ยนสเกลเป็น 0.8 เมื่อออกจากหน้าจอ?
iamthevoid

ใช้งานได้แล้ว! แต่เมื่อฉันพยายามซูมเค้าโครงตรงกลางมันจะซูมไปที่ด้านบนและด้านล่าง มองไม่เห็นด้านซ้ายและขวาเนื่องจากช่องว่างภายใน โปรดดูคำถามstackoverflow.com/questions/52710076/…
Anooj Krishnan G

73

คำตอบโดย @JijuInduchoodan สมบูรณ์แบบและใช้งานได้ อย่างไรก็ตามเนื่องจากฉันค่อนข้างใหม่กับ Android ฉันจึงต้องใช้เวลาสักพักในการทำความเข้าใจและตั้งค่าให้ถูกต้อง ดังนั้นฉันจึงโพสต์คำตอบนี้เพื่อใช้อ้างอิงในอนาคตและช่วยเหลือคนอื่นที่อยู่ในรองเท้าเดียวกันกับฉัน

if (viewPager == null) 
        {

            // Initializing view pager
            viewPager = (ViewPager) findViewById(R.id.vpLookBook);

            // Disable clip to padding
            viewPager.setClipToPadding(false);
            // set padding manually, the more you set the padding the more you see of prev & next page
            viewPager.setPadding(40, 0, 40, 0);
            // sets a margin b/w individual pages to ensure that there is a gap b/w them
            viewPager.setPageMargin(20);
        }

ไม่จำเป็นต้องตั้งค่าความกว้างใด ๆ ให้กับViewPager'sเพจในอะแดปเตอร์ ViewPagerไม่มีรหัสเพิ่มเติมที่จำเป็นเพื่อดูหน้าก่อนหน้านี้และต่อไปใน อย่างไรก็ตามหากคุณต้องการเพิ่มพื้นที่ว่างที่ด้านบนและด้านล่างของแต่ละหน้าคุณสามารถตั้งค่าโค้ดต่อไปนี้เป็นViewPager'sเลย์เอาต์หลักของเพจลูกได้

android:paddingTop="20dp"
android:paddingBottom="20dp"

ViewPager ขั้นสุดท้าย

นี่จะเป็นรูปลักษณ์สุดท้ายของ ViewPager


69

วิธีแก้ไขด้วย ViewPager2 ใหม่

ปัจจุบันคุณควรพิจารณาใช้ViewPager2ซึ่ง"แทนที่ ViewPager โดยกล่าวถึงจุดเจ็บปวดส่วนใหญ่ของรุ่นก่อน" :

  • ขึ้นอยู่กับ RecyclerView
  • รองรับโครงร่าง RTL (ขวาไปซ้าย)
  • การสนับสนุนแนวตั้ง
  • การสนับสนุน Fragment ที่เชื่อถือได้ (รวมถึงการจัดการการเปลี่ยนแปลงคอลเลกชัน Fragment ที่อยู่เบื้องหลัง)
  • ภาพเคลื่อนไหวการเปลี่ยนแปลงชุดข้อมูล (รวมถึงDiffUtilการสนับสนุน)

ผลลัพธ์

ป้อนคำอธิบายภาพที่นี่

รหัส

ในกิจกรรม / ส่วนของคุณตั้งค่า ViewPager2:

// MyRecyclerViewAdapter is an standard RecyclerView.Adapter :)
viewPager2.adapter = MyRecyclerViewAdapter() 

// You need to retain one page on each side so that the next and previous items are visible
viewPager2.offscreenPageLimit = 1

// Add a PageTransformer that translates the next and previous items horizontally
// towards the center of the screen, which makes them visible
val nextItemVisiblePx = resources.getDimension(R.dimen.viewpager_next_item_visible)
val currentItemHorizontalMarginPx = resources.getDimension(R.dimen.viewpager_current_item_horizontal_margin)
val pageTranslationX = nextItemVisiblePx + currentItemHorizontalMarginPx
val pageTransformer = ViewPager2.PageTransformer { page: View, position: Float ->
    page.translationX = -pageTranslationX * position
    // Next line scales the item's height. You can remove it if you don't want this effect
    page.scaleY = 1 - (0.25f * abs(position))
    // If you want a fading effect uncomment the next line:
    // page.alpha = 0.25f + (1 - abs(position))
}
viewPager2.setPageTransformer(pageTransformer)

// The ItemDecoration gives the current (centered) item horizontal margin so that
// it doesn't occupy the whole screen width. Without it the items overlap
val itemDecoration = HorizontalMarginItemDecoration(
    context,
    R.dimen.viewpager_current_item_horizontal_margin
)
viewPager2.addItemDecoration(itemDecoration)

เพิ่มHorizontalMarginItemDecorationซึ่งเป็นเรื่องเล็กน้อยItemDecoration:

/**
 * Adds margin to the left and right sides of the RecyclerView item.
 * Adapted from https://stackoverflow.com/a/27664023/4034572
 * @param horizontalMarginInDp the margin resource, in dp.
 */
class HorizontalMarginItemDecoration(context: Context, @DimenRes horizontalMarginInDp: Int) :
    RecyclerView.ItemDecoration() {

    private val horizontalMarginInPx: Int =
        context.resources.getDimension(horizontalMarginInDp).toInt()

    override fun getItemOffsets(
        outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
    ) {
        outRect.right = horizontalMarginInPx
        outRect.left = horizontalMarginInPx
    }

}

เพิ่มมิติที่ควบคุมว่าจะมองเห็นรายการก่อนหน้า / ถัดไปได้เท่าใดและระยะขอบแนวนอนของรายการปัจจุบัน:

<dimen name="viewpager_next_item_visible">26dp</dimen>
<dimen name="viewpager_current_item_horizontal_margin">42dp</dimen>

ป้อนคำอธิบายภาพที่นี่

สุดท้ายเพิ่มลงในViewPager2เค้าโครงของคุณ:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

สิ่งสำคัญอย่างหนึ่ง: ViewPager2ไอเท็มต้องมีlayout_height="match_parent"(มิฉะนั้นจะพ่น IllegalStateException) ดังนั้นคุณควรทำสิ่งต่างๆเช่น:

<androidx.cardview.widget.CardView 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" <-- this!
    app:cardCornerRadius="8dp"
    app:cardUseCompatPadding="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="280dp">

        <!-- ... -->

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

ตัวอย่าง PageTransformer

Google ได้เพิ่มคำแนะนำเกี่ยวกับ ViewPager2 ซึ่งมีPageTransformerการใช้งาน2 แบบที่คุณสามารถใช้เป็นแรงบันดาลใจได้: https://developer.android.com/training/animation/screen-slide-2

เกี่ยวกับ ViewPager2 ใหม่


ปัญหาเดียวกันกับอุปกรณ์ oreo การเริ่มต้นและสิ้นสุดช่องว่างภายในทำงานได้ตามที่คาดไว้ในอุปกรณ์อื่น ๆ แต่ Oreo หลังจาก ViewPager2 PageTransformer แก้ไขปัญหาแล้วการพายยังคงเหมือนเดิมและฉันต้องเพิ่มviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr

ฉันต้องเลื่อนดูเพจเจอร์เล็กน้อยเพื่อให้ได้เอฟเฟกต์นี้
Muhammad Saqib

ไม่เป็นไรฉันลืมเพิ่มบรรทัดนี้setOffscreenPageLimit(1):)
Muhammad Saqib

นี่เป็นทางออกที่ดีที่สุดที่ฉันเคยพบ ทำงานได้อย่างสมบูรณ์แบบ แต่ใช่อย่าลืมตั้งค่าความกว้างของรายการของ ViewPager2 ความสูงเป็น MATCH_PARENT
khushbu

26

ในปี 2560 พฤติกรรมดังกล่าวสามารถทำได้อย่างง่ายดายโดยใช้RecyclerViewกับPagerSnapHelper (เพิ่มในเวอร์ชัน 25.1.0 ของไลบรารีสนับสนุน v7): 

ป้อนคำอธิบายภาพที่นี่

เมื่อไม่นานมานี้ฉันต้องการคุณสมบัติเหมือนโปรแกรมดูเพจและเตรียมห้องสมุดเล็ก ๆ :

MetalRecyclerPagerView - คุณสามารถค้นหาโค้ดทั้งหมดพร้อมกับตัวอย่างได้ที่นั่น

ส่วนใหญ่ประกอบด้วยไฟล์คลาสเดียว: MetalRecyclerViewPager.java (และสอง xmls: attrs.xmlและids.xml )

หวังว่าจะช่วยใครสักคนและจะช่วยประหยัดเวลาได้บ้าง :)


นอกประเด็นเพราะบางครั้งต้องใช้เพจเจอร์เท่านั้น แต่ยินดีที่ได้รู้จัก! ขอบคุณสำหรับการแบ่งปัน!
sud007

นี่มันเจ๋งมาก. ฉันมีรหัสตัวช่วย RecyclerView มากมาย เพียงแค่เพิ่มแบบธรรมดาnew PagerSnapHelper().attachToRecyclerView(recyclerView)และฉันก็มีการหักหน้า
Steve

9

หากใครยังคงมองหาวิธีแก้ปัญหาฉันได้ปรับแต่ง ViewPage เพื่อให้บรรลุโดยไม่ต้องใช้ระยะขอบติดลบค้นหาโครงการตัวอย่างที่นี่https://github.com/44kksharma/Android-ViewPager-Carousel-UI ส่วนใหญ่ควรใช้งานได้ แต่คุณ ยังสามารถกำหนดระยะขอบหน้าด้วย mPager.setPageMargin(margin in pixel);


8

คุณสามารถทำได้ในไฟล์ xml เพียงใช้โค้ดด้านล่าง:

 android:clipToPadding="false"
 android:paddingLeft="XX"
 android:paddingRight="XX"

ตัวอย่างเช่น:

<androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingLeft="30dp"
        android:paddingRight="30dp" />

หมายเหตุ: หากคุณต้องการช่องว่างระหว่างหน้าให้ตั้งค่า padding / margin เป็นส่วนย่อย


3
ฉันโหวตลง ขอโทษครับ ได้ผลขนาดนี้ !!
โหวตเพิ่ม

1

สำหรับผู้ที่มีปัญหานี้บนหน้าจอต่างๆ

mPager.setClipToPadding(false);
DisplayMetrics displayMetrics = new DisplayMetrics();
self.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int paddingToSet = width/4; //set this ratio according to how much of the next and previos screen you want to show.
mPager.setPadding(paddingToSet,0,paddingToSet,0);

0

โปรดทราบว่าเมื่อตั้งค่าไม่มีการเว้นช่องว่างเป็นศูนย์ให้กับ viewpager ตำแหน่ง edgeeffect ของ viewpager จะยุ่งเหยิงนี่เป็นข้อบกพร่องของ viewpager โปรดดูที่นี่: ข้อผิดพลาด viewpager edgeeffect

คุณสามารถปิดการใช้งานเอฟเฟกต์ขอบได้โดยการตั้งค่าandroid:overScrollMode="never"เป็น viewpager หรือคุณสามารถแก้ไขข้อบกพร่องด้วยคลาส EdgeEffect รุ่นแก้ไขเล็กน้อย: แก้ไข ViewPagerEdgeEffect


0
 override fun getPageWidth(position: Int): Float {
    return 0.7f
}

เพิ่มสิ่งนี้ในไฟล์คลาสอะแดปเตอร์สิ่งนี้ใช้ได้กับฉัน


-11

ใช้อะแด็ปเตอร์แฟรกเมนต์และคลาสนี้เพื่อดู viewpager ในการเลื่อนซ้ายและขวาเพิ่มคลาสที่จำเป็นเพื่อเลื่อนเพื่อดูหน้าถัดไป

package com.rmn.viewpager;

import java.util.List;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

/**
 * The <code>PagerAdapter</code> serves the fragments when paging.
 * @author mwho
 */
public class PagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    /**
     * @param fm
     * @param fragments
     */
    public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }
    /* (non-Javadoc)
     * @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
     */
    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    /* (non-Javadoc)
     * @see android.support.v4.view.PagerAdapter#getCount()
     */
    @Override
    public int getCount() {
        return this.fragments.size();
    }
}



package com.manishkpr.viewpager;


import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class ViewPagerAdapter extends FragmentPagerAdapter {
    private Context _context;

    public ViewPagerAdapter(Context context, FragmentManager fm) {
        super(fm);  
        _context=context;

        }
    @Override
    public Fragment getItem(int position) {
        Fragment f = new Fragment();
        switch(position){
        case 0:
            f=LayoutOne.newInstance(_context);  
            break;
        case 1:
            f=LayoutTwo.newInstance(_context);  
            break;
        }
        return f;
    }
    @Override
    public int getCount() {
        return 2;
    }

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.