简体   繁体   English

Android ViewPager-动态宽度和多个可见页面

[英]Android ViewPager - Dynamic width & multiple visible pages

My issue is quite complex and I have hard time finding a solution to achieve the following : 我的问题很复杂,我很难找到实现以下目标的解决方案:

I need to have a sort of legend (a stepper) layout where a child is made of left bar, followed by a circle, followed by a right bar. 我需要一种图例(步进)布局,其中一个子项由左栏,一个圆圈和一个右栏组成。 Strickly speaking somethind like "-o-". 棘手地讲类似“ -o-”的东西。 So a serie of children looks like this : "-ooooo". 因此,一系列的孩子看起来像这样:“-ooooo”。 When the legend focuses on a child meaning that the current child is this one, this child has a bigger circle and longer bars: "--O--". 当图例着重于一个孩子时,意味着当前孩子是这个孩子,这个孩子有一个更大的圆圈和更长的杠:“-O--”。

The final rendering looks therefore like this : "-oo--O--oo-". 因此,最终渲染看起来像这样:“-oo--O--oo-”。

Each child ("-o-") corresponds to a specific item in a database. 每个子项(“ -o-”)对应于数据库中的特定项目。 When a child gets focuses ("--O--"), the relative item is displayed below. 当孩子获得焦点时(“ --O--”),相对项显示在下面。 When the user swipes from right to left, the next item is showed, whereas a swipe from left to right will display the previous item. 当用户从右向左滑动时,将显示下一项,而从左向右滑动将显示前一项。

When swiping, to show which child will display its corresponding item, say child will be animated to show it has focus. 滑动时,要显示哪个孩子将显示其对应的项目,请说将对孩子进行动画处理以显示其具有焦点。 I use a Animator to : 我使用Animator来:

  1. increase the bars widths and the circle size of the child that is getting the focus 增加获得焦点的孩子的横条宽度和圆圈大小
  2. to decrease these values of the previously focused child. 降低先前关注的孩子的这些价值。

Displaying a legend requires to see what's before and what's next. 要显示图例,需要查看之前和之后的内容。

I believe using a ViewPager will help me achieve the following : 我相信使用ViewPager可以帮助我实现以下目标:

  1. it has an "anchor effect", meaning a swipe will move from child to child, centering on the circle : the circle between the bars is the anchor, so to speak. 它具有“锚定效果”,这意味着滑动会以圆圈为中心在一个子对象之间移动:可以说,条形之间的圆圈是锚点。
  2. I can display multiple pages on the screen by overriding the getPageWidth() method of my custom adapter 我可以通过覆盖自定义adaptergetPageWidth()方法在屏幕上显示多个页面

The other solution I had in mind is the HorizontalScrollView . 我想到的另一个解决方案是HorizontalScrollView If I were to use it, depending on the swipe properties (strengh, speed), the legend would indeterminately scroll without anchoring the circle. 如果要使用它,则根据滑动属性(强度,速度),图例将不确定地滚动而不锚定圆。

But using the ViewPager has a big problem: each page has the same width. 但是使用ViewPager存在一个大问题:每个页面具有相同的宽度。 However, the anchored child of the legend needs to be bigger (so needs more width). 但是,图例的锚定子项需要更大(因此需要更大的宽度)。

So how can I change the width dynamically ? 那么如何动态更改宽度?

Unless I can customize a HorizontalScrollView to add the anchor effect by intercepting in swipe ? 除非我可以自定义HorizontalScrollView以通过在滑动中拦截来添加锚点效果?

我还认为CarouselLayoutManager可能包含您想要的效果。

If you are using a ViewPager , I think the best way to do this would be with an OnPageChangeListener . 如果您使用的是ViewPager ,我认为最好的方法是使用OnPageChangeListener You will get callbacks as the user is swiping left/right so that you can size your indicators based on the location of the user's swipe. 当用户向左/向右滑动时,您将获得回调,以便可以根据用户滑动的位置来调整指标的大小。

    private int mCurrentPage = 0;

    viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // positionOffset goes from 0.0 to just under 1.0 for the leftmost page

            float otherOffset = 1.0 - positionOffset;

            if (position == mCurrentPage) { // user is incrementing page, i.e. swiping left
                // size of current page indicator based on otherOffset
                // size of next page indicator based on positionOffset

            } else { // user is decrementing page, i.e. swiping right

                // size of current page indicator based on positionOffset
                // size of previous page indicator based on otherOffset
            }
        }

        @Override
        public void onPageSelected(int position) {
            mCurrentPage = position;

            // ... set final sizes: page @ position = 1.0 all others 0.0
        }
    });

Here's how to understand position and positionOffset : When a page has settled, it is centered. 这是了解positionpositionOffset :页面沉降后将其居中。 Let's say the current page position == 1 (ie page 2). 假设当前页面位置== 1(即第2页)。

  • First case: User swipes left to get to the next page. 第一种情况:用户向左滑动即可进入下一页。 Say the user swipes 10% of the distance to get to the next page. 假设用户滑动距离的10%即可进入下一页。 position will be 1 (leftmost displayed) and positionOffset will be 0.1 (viewport left edge is at 10% of leftmost page). position将为1(显示在最左侧), positionOffset将为0.1 (视口的左边缘为最左边页面的10%)。 So as user swipes, positionOffset will go from 0.0 to just below 1.0 . 因此,当用户滑动时, positionOffset将从0.0变为略低于1.0

  • Second case: User swipes right to get to the previous page. 第二种情况:用户向右滑动即可到达上一页。 When the user swipes 10% of the distance to the previous page, position will be 0 (leftmost displayed) and positionOffset will be 0.9 (viewport left edge is at 90% of the leftmost page). 当用户向上一页滑动距离的10%时, position将为0(最左侧显示),而positionOffset将为0.9 (视口左边缘位于最左侧页面的90%)。 So as user swipes, positionOffset will go from just under 1.0 to 0.0 . 因此,当用户滑动时, positionOffset将从1.0变为0.0

As for the indicators themselves, I did a similar pager indicator where I used a LinearLayout with a horizontal orientation, adding a child indicator view for each page. 至于指示器本身,我做了类似的寻呼机指示器,在其中我使用了水平放置的LinearLayout ,为每个页面添加了一个子指示器视图。 I used pagerAdapter.getCount() to get the number of views to add. 我使用pagerAdapter.getCount()获取要添加的视图数。

Your indicator is more complex with the animation, but if I were to do this, I would use a plain View with ScaleDrawable backgrounds for graphics that could change size. 您的指示符与动画相比更为复杂,但是如果要执行此操作,则我将使用具有ScaleDrawable背景的普通View作为可更改大小的图形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM