【问题标题】:Align the child views in center of the ViewPager android在 ViewPager android 的中心对齐子视图
【发布时间】:2019-03-30 00:43:16
【问题描述】:

我需要将子视图设置为 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>

当前屏幕

预期屏幕

【问题讨论】:

  • 我现在通过自定义 ViewPager 完成了这项工作。
  • 你搞定了吗?我面临同样的问题@noundla
  • 是的。给我你的邮箱,我可以发给你。
  • 非常感谢。我的地址:wangbourne@gmail.com
  • 我给你发邮件。检查并告诉我。

标签: android android-viewpager center


【解决方案1】:

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

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

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

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

【讨论】:

  • 感谢您的回答。我认为这不会像我预期的那样给出结果,因为如果我们留出余地,这些观点就不应该放在一边。但是,我通过自定义 ViewPager 类中的 scrollToItem() 方法来做到这一点。我应该发布我的 ViewPager 课程,但是它有更多的字符,所以我无法在这里发布答案。我想结束这个问题。
  • 我就是这样做的,但使用的是 FrameLayouts。这个想法是放弃使用 getPageWidth() (将其保留为 1.0f)并使用负边距来引入相邻页面。在我的页面布局中,我使用了一个根 FrameLayout(参数并不重要,因为它们将由 ViewPager 设置)和一个固定宽度的子 FrameLayout,我放置了所有页面的内容。然后在我的活动中,我将按以下方式计算负边距:margin = viewpager.getWidth() - pageWidth; viewpager.setPageMargin(-margin);其中pageWidth是我上面指定的子FrameLayout的固定宽度
  • 是的!这样做了
【解决方案2】:

对于任何因 OP 没有用解决方案更新他的问题而感到不安的人,这里有一个链接解释了如何以最小的努力在 XML 中解决这个问题:http://blog.neteril.org/blog/2013/10/14/android-tip-viewpager-with-protruding-children/

基本上,当您在 XML 中声明您的 viewpager 时,给它相同的左右填充并设置 android:clipToPadding="false"。 (他的 xml 示例中缺少 clipToPadding 并且是实现此效果所必需的)

【讨论】:

    【解决方案3】:

    最后,我在 GitHub 中添加了这个问题的解决方案。我已经做了一些漂亮的技巧来获得解决方法。您可以从以下链接获取项目(实际上我计划创建一个带有解释的博客,但我没有那么多时间去做)。

    这里是link(https://github.com/noundla/Sunny_Projects/tree/master/CenterLockViewPager)

    您必须将文件从com.noundla.centerviewpagersample.comps 包复制到您的项目。您可以在 MainActivity 类中看到该 Viewpager 的用法。

    如果有人对此有问题,请告诉我。

    【讨论】:

      【解决方案4】:

      我在post 中找到了解决方案,位于我使用的代码下方:

      // 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);
          }
      

      这就是你所需要的

      【讨论】:

        【解决方案5】:

        您可以为 viewPager 使用填充并设置 clipToPadding false

        Java

        viewPager.setClipToPadding(false);
        viewPager.setPadding(50, 0, 50, 0);
        

        科特林

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

        【讨论】:

          【解决方案6】:

          我必须在 不同页面宽度的视图寻呼机中居中当前页面,因此不适合使用填充的解决方案。用户滚动也被禁用(它是标签栏视图寻呼机,由另一个视图寻呼机滚动)。这是一个非常简单的解决方案 - 只需像这样覆盖 ViewPager.ScrollTo 方法(C# 代码,Xamarin):

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

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

          【讨论】:

            【解决方案7】:

            扩展 Horizo​​ntalScrollView 类作为滚动视图的父级。在 onMeasure() 方法中,您可以指定每个孩子的宽度和高度。方式有点麻烦,但效果会很好,可以很好的掌握孩子的观点。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-11-27
              • 2021-08-08
              • 1970-01-01
              • 2013-05-30
              • 1970-01-01
              • 1970-01-01
              • 2017-04-08
              相关资源
              最近更新 更多