将ViewPager中的子视图居中对齐

18

我需要将子视图设置为ViewPager的中心,并且我还想在当前视图的两侧显示下一个和上一个视图的一部分(如下所示的当前屏幕下方1)。但是目前,当前视图从ViewPager的左侧开始(如预期屏幕下方2)。我该怎么做才能实现这个?

以下是我的代码..

MyViewPagerAdapter

public class MyViewPagerAdapter extends PagerAdapter {
    private Activity mActivity;
    private int mPageCount;
    public MyViewPagerAdapter(Activity activity,int pageCount) {
        mActivity = activity;
        mPageCount = pageCount;
    }

    @Override
    public int getCount() {
        return mPageCount;
    }

    @Override
    public boolean isViewFromObject(View view, Object obj) {
        return (view ==(View)obj);
    }

    @Override
    public Object instantiateItem(ViewGroup container,final int position) {
        ViewGroup viewGroup = (ViewGroup)mActivity.getLayoutInflater().inflate(
                R.layout.item_view, null);

        viewGroup.setBackgroundColor(randomColor());

        TextView textView = (TextView)viewGroup.findViewById(R.id.textView1);
        textView.setText("Page: "+(position+1));
        Button button = (Button) viewGroup.findViewById(R.id.button1);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(mActivity, "Hey, Its clicked!!! at page "+(position+1), Toast.LENGTH_LONG).show();
            }
        });
        container.addView(viewGroup);
        return viewGroup;
    }

    Random rnd = new Random();
    private int randomColor(){
        return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        //must be overridden else throws exception as not overridden.
        Log.d("Tag", collection.getChildCount()+"");
        collection.removeView((View) view);
    }

    @Override
    public float getPageWidth(int position) {
        return 0.8f;
    }
}

MainActivity

public class MainActivity extends Activity {
    private ViewPager viewPager;
    LinearLayout linearLayout;
    private int ID = 100; 

    private final int count = 8;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        linearLayout  = (LinearLayout) findViewById(R.id.indicator_layout);
        generateIndicators(count);


        MyViewPagerAdapter adapter = new MyViewPagerAdapter(this, count);
        viewPager.setAdapter(adapter);
        viewPager.setOnPageChangeListener(new OnPageChangeListener() {
            int oldPosition = 0;
            @Override
            public void onPageSelected(int position) {
                //this changes the old position's view state image
                ((TextView)linearLayout.getChildAt(oldPosition)).setText("");
                oldPosition = position;


                //this changes the current position's view state image
                ((TextView)linearLayout.getChildAt(position)).setText((position+1)+"");

            }
            //this method will be called repeatedly upto another item comes as front one(active one)
            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {


            }
            //this will be called as per scroll state
            @Override
            public void onPageScrollStateChanged(int arg0) {


            }
        });

        viewPager.setOffscreenPageLimit(4);

    }

    private void generateIndicators(int count) {
        /// Converts 14 dip into its equivalent px
        int padd = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());

        for(int i=0;i<count;i++){
            TextView textView = new TextView(this);
            textView.setId(ID+i);
            final int currentItem = i;
            textView.setBackgroundResource(R.drawable.white_cell);
            textView.setPadding(padd,padd,padd,padd);
            /// Converts 14 dip into its equivalent px
            int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
            textView.setTextSize(size);
            textView.setGravity(Gravity.CENTER);
            /// Converts 14 dip into its equivalent px
            int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(px, px);
            linearLayout.addView(textView,params);
        }

        ((TextView)linearLayout.getChildAt(0)).setText("1");

    }





}

activity_main.xml

<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"
    tools:context=".MainActivity" >



   <android.support.v4.view.ViewPager
       android:id="@+id/viewPager"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:layout_alignParentLeft="true"
       android:layout_alignParentTop="true" >
   </android.support.v4.view.ViewPager>


   <LinearLayout
       android:id="@+id/indicator_layout"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_centerHorizontal="true"
       android:layout_marginBottom="19dp" >
   </LinearLayout>

</RelativeLayout>

item_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="match_parent"
    android:id="@+id/root_view"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="click me" />

</LinearLayout>

当前屏幕 当前屏幕

期望屏幕 期望屏幕


是的,请给我您的电子邮件地址,我可以将其发送给您。 - Noundla Sandeep
非常感谢。我的地址:wangbourne@gmail.com - LiangWang
我给你发送了一封邮件,请查收并告诉我。 - Noundla Sandeep
您是否成功实现了预期的屏幕呈现?@noundla - Shad
可以的,我可以给你。你能告诉我如何发布大量代码以供所有人使用吗? - Noundla Sandeep
显示剩余2条评论
7个回答

12

对于我实现的一个类似应用,我使用了标准的 ViewPager,方式如下:

  • 使页面全屏并在内部布局中添加实际内容。例如,将全屏布局设为具有透明背景的 RelativeLayout,而将实际内容放置在父布局中心的另一 RelativeLayout 中。如果我没记错的话,这样做的原因是,仅以内部布局作为页面时,在某些设备上(如Galaxy Nexus)ViewPager 不会占用所有屏幕宽度。

  • 使用 ViewPager.setPageMargin() 设置负页边距,即您要显示多少个下一个/上一个页面。确保它仅重叠父全屏布局的透明区域。

  • 调用 ViewPager.setOffscreenPageLimit() 将离屏页面数量从默认值 1 调整至至少 2,以确保通过真正创建屏幕外页面来实现平滑翻页。否则,您将看到下一个/上一个页面在部分显示在屏幕上时被绘制。


谢谢您的回答。我认为这样做不能得到我期望的结果,因为如果我们给出边距,那些视图不应该出现在旁边。然而,我通过自定义ViewPager类中的scrollToItem()方法来实现了它。我本打算发布我的ViewPager类,但它有更多的字符,所以我无法在这里发布答案。我想关闭这个问题。 - Noundla Sandeep
这是我使用FrameLayouts的方法。我的想法是放弃使用getPageWidth()(将其保留为1.0f),并使用负边距将相邻页面带入。在我的页面布局中,我使用了一个根FrameLayout(参数不太重要,因为它们将由ViewPager设置),以及一个具有固定宽度的子FrameLayout,我将所有页面内容都放在其中。然后在我的活动中,我会计算负边距如下:margin = viewpager.getWidth() - pageWidth; viewpager.setPageMargin(-margin);其中pageWidth是我上面指定的子FrameLayout的固定宽度。 - Lumbi
是的!它做到了。 - Touré Holder

10

6
最后,我已经在GitHub上添加了这个问题的解决方案。我已经采用了一些巧妙的技巧来获得工作解决方案。您可以从下面的链接中获取项目(实际上我计划创建一个带有解释的博客,但是我没有那么多时间去做)。
这里是链接(https://github.com/noundla/Sunny_Projects/tree/master/CenterLockViewPager)
你必须将com.noundla.centerviewpagersample.comps包中的文件复制到你的项目中。你可以在MainActivity类中看到Viewpager的使用方法。
如果有人遇到问题,请告诉我。

2

我在这篇文章中找到了解决方案,以下是我使用的代码:

// Offset between sibling pages in dp
int pageOffset = 20;

// Visible part of sibling pages at the edges in dp
int sidePageVisibleWidth = 10;

// Horizontal padding will be
int horPadding = pageOffset + sidePageVisibleWidth;

// Apply parameters
viewPager.setClipToPadding(false);
viewPager.setPageMargin(UIUtil.dpToPx(pageOffset, getContext()));
viewPager.setPadding(UIUtil.dpToPx(horPadding, getContext()), 0, UIUtil.dpToPx(horPadding, getContext()), 0);

dpToPx代码:

 public static int dpToPx(int dp, Context context) {
        float density = context.getResources().getDisplayMetrics().density;
        return Math.round((float) dp * density);
    }

这就是你需要的全部


1
你可以使用padding来设置viewPager,并将clipToPadding设为false。 Java
viewPager.setClipToPadding(false);
viewPager.setPadding(50, 0, 50, 0);

Kotlin
 viewPager.clipToPadding = false
 viewPager.setPadding(50, 0, 50, 0)

0

我需要在视图页面中居中当前页,但由于页面宽度不同,使用填充的解决方案并不适用。同时,用户滚动被禁用(这是一个选项卡栏视图页面,由另一个视图页面滚动)。以下是一个非常简单的解决方案 - 只需像这样覆盖ViewPager.ScrollTo方法即可(C#代码,Xamarin):

public override void ScrollTo(int x, int y)
{
    x -= (int) (MeasuredWidth * (1 - Adapter.GetPageWidth(CurrentItem)) / 2);

    base.ScrollTo(x, y);
}

如果您为每个片段计算页面宽度,请不要忘记将它们缓存到数组中。


-2

HorizontalScrollView类扩展为滚动视图的父类。在onMeasure()方法中,您可以指定每个子项的宽度和高度。虽然有点繁琐,但效果很好,您可以很好地控制子视图。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接