5

在这里,我需要一个类似画廊的视图,一次只能在屏幕上显示三个图像。在这种情况下,中间图像将大于其两侧的其他两个图像。

如果用户滚动视图,下一个图像将像在画廊中一样在屏幕上滑动,并且一次只显示三个图像,其中中心图像在屏幕上显示时应自动缩放,其余两个应小于它.

在这里我不能使用画廊,因为它在 android 中已被贬值。

在 viewpager 的帮助下,我可以使用此链接上的代码制作类似画廊的视图。它一次只在屏幕上显示三个图像,这符合我的一个要求。但我无法获得屏幕上可见的中央图像并对其进行缩放。虽然我能够在屏幕上获得点击的图像。

有人可以告诉我我需要在哪里修改代码以及我需要在其中添加什么以从屏幕上显示的图像中获取位于中心的图像并对其进行缩放。

我知道根据 viewpager 屏幕上没有中心图像,并且由于代码的修改,它一次只在屏幕上显示三个图像。

我也试过: -

  • 具有水平滚动的 GridView
  • 水平线性布局的 Horizo​​ntalScrollView

但 viewpager 似乎是一个更好的解决方案,因为由于 viewpager 的固有属性,它在屏幕上仅停止滚动三个项目。

如果有人知道任何其他方法来实现它,请告诉我,我会尝试的。

PS对于任何想要完整代码的人,我已将其添加为答案,它也具有缩放功能。在接受的答案中只添加了一些内容。:)

4

2 回答 2

14

以下代码将帮助您制作一个类似画廊的视图,该视图将具有中心锁定。它对触摸和滑动都有反应。它一次在屏幕上显示三个图像,并且中心图像被缩放。

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class CenteringHorizontalScrollView extends HorizontalScrollView implements View.OnTouchListener {

    private Context mContext;
    private static final int SWIPE_PAGE_ON_FACTOR = 10;
    private int mActiveItem;
    private float mPrevScrollX;
    private boolean mStart;
    private int mItemWidth;

    View targetLeft, targetRight;
    ImageView leftImage, rightImage;

    public CenteringHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext=context;
        mItemWidth = 100; // or whatever your item width is.
        setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int x = (int) event.getRawX();

        boolean handled = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (mStart) {
                    mPrevScrollX = x;
                    mStart = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                mStart = true;
                int minFactor = mItemWidth / SWIPE_PAGE_ON_FACTOR;

                if ((mPrevScrollX - (float) x) > minFactor) {
                    if (mActiveItem < getMaxItemCount() - 1) {
                        mActiveItem = mActiveItem + 1;
                    }
                }else if (((float) x - mPrevScrollX) > minFactor) {
                    if (mActiveItem > 0) {
                        mActiveItem = mActiveItem - 1;
                    }
                }

                scrollToActiveItem();

                handled = true;
                break;
        }

        return handled;
    }

    private int getMaxItemCount() {
        return ((LinearLayout) getChildAt(0)).getChildCount();
    }

    private LinearLayout getLinearLayout() {
        return (LinearLayout) getChildAt(0);
    }

    /**
     * Centers the current view the best it can.
     */
    public void centerCurrentItem() {
        if (getMaxItemCount() == 0)
            return;

        int currentX = getScrollX();
        View targetChild;
        int currentChild = -1;

        do {
            currentChild++;
            targetChild = getLinearLayout().getChildAt(currentChild);
        } while (currentChild < getMaxItemCount() && targetChild.getLeft() < currentX);

        if (mActiveItem != currentChild) {
            mActiveItem = currentChild;
            scrollToActiveItem();
        }
    }

    /**
     * Scrolls the list view to the currently active child.
     */
    private void scrollToActiveItem() {
        int maxItemCount = getMaxItemCount();
        if (maxItemCount == 0)
            return;

        int targetItem = Math.min(maxItemCount - 1, mActiveItem);
        targetItem = Math.max(0, targetItem);

        mActiveItem = targetItem;

        // Scroll so that the target child is centered
        View targetView = getLinearLayout().getChildAt(targetItem);
    
        ImageView centerImage = (ImageView)targetView;
        int height=300;//set size of centered image
        LinearLayout.LayoutParams flparams = new LinearLayout.LayoutParams(height, height);
        centerImage.setLayoutParams(flparams);

        //get the image to left of the centered image
        if((targetItem-1)>=0){
            targetLeft = getLinearLayout().getChildAt(targetItem-1);
            leftImage = (ImageView)targetLeft;
            int width=250;//set the size of left image
            LinearLayout.LayoutParams leftParams = new LinearLayout.LayoutParams(width,width);
            leftParams.setMargins(0, 30, 0, 0);
            leftImage.setLayoutParams(leftParams);
        }

        //get the image to right of the centered image
        if((targetItem+1)<maxItemCount){
            targetRight = getLinearLayout().getChildAt(targetItem+1);
            rightImage = (ImageView)targetRight;
            int width=250;//set the size of right image
            LinearLayout.LayoutParams rightParams = new LinearLayout.LayoutParams(width,width);
            rightParams.setMargins(0, 30, 0, 0);
            rightImage.setLayoutParams(rightParams);
        }
    
        int targetLeft = targetView.getLeft();
        int childWidth = targetView.getRight() - targetLeft;
    
        int width = getWidth() - getPaddingLeft() - getPaddingRight();
        int targetScroll = targetLeft - ((width - childWidth) / 2);
    
        super.smoothScrollTo(targetScroll, 0);
    }

    /**
     * Sets the current item and centers it.
     * @param currentItem The new current item.
     */
    public void setCurrentItemAndCenter(int currentItem) {
        mActiveItem = currentItem;
        scrollToActiveItem();
    }

}

在您的 xml 中添加水平滚动视图,如下所示:-

<com.yourpackagename.CenteringHorizontalScrollView
    android:id="@+id/HSVImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/Horizontalalternative">

    <LinearLayout
        android:id="@+id/linearImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    </LinearLayout>
</com.yourpackagename.CenteringHorizontalScrollView>

在您的活动中定义线性布局。

LinearLayout imageGallery;

然后得到它如下: -

imageGallery=(LinearLayout)findViewById(R.id.linearImage);

现在您必须将 imageView 添加到您的 LinearLayout。在这里,我假设您的可绘制文件夹中有图像,并且您已经制作了一组要添加到图库的图像的 id。所以你可以在你的活动中通过以下方法来做到这一点: -

for(int i=0; i<lengthOfImageIdArray; i++){
    ImageView image=new ImageView(YourActivityName.this);
    image.setBackgroundResource(yourArrayName[i]);
    imageGallery.addView(image);
}

您还可以动态设置图像的宽度,以便它们适合每个屏幕,只需一点额外的努力。

于 2013-09-24T05:24:39.057 回答
12

在 ViewPager 中覆盖setPrimaryItem并使中心项目更大。

将 Horizo​​ntalScrollView 与 LinearLayout 一起使用有什么问题?如果它居中,您也许可以做类似的事情(假设您已经

/**
 * A centering HSV loosely based on http://iotasol.blogspot.com/2011/08/creating-custom-horizontal-scroll-view.html
 */
public class CenteringHorizontalScrollView extends HorizontalScrollView implements View.OnTouchListener {

    private static final int SWIPE_PAGE_ON_FACTOR = 10;

    private int mActiveItem;

    private float mPrevScrollX;

    private boolean mStart;

    private int mItemWidth;

    public CenteringHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mItemWidth = 100; // or whatever your item width is.
        setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int x = (int) event.getRawX();

        boolean handled = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (mStart) {
                    mPrevScrollX = x;
                    mStart = false;
                }

                break;
            case MotionEvent.ACTION_UP:
                mStart = true;
                int minFactor = mItemWidth / SWIPE_PAGE_ON_FACTOR;

                if ((mPrevScrollX - (float) x) > minFactor) {
                    if (mActiveItem < getMaxItemCount() - 1) {
                        mActiveItem = mActiveItem + 1;
                    }
                }
                else if (((float) x - mPrevScrollX) > minFactor) {
                    if (mActiveItem > 0) {
                        mActiveItem = mActiveItem - 1;
                    }
                }

                scrollToActiveItem();

                handled = true;
                break;
        }

        return handled;
    }

    private int getMaxItemCount() {
        return ((LinearLayout) getChildAt(0)).getChildCount();
    }

    private LinearLayout getLinearLayout() {
        return (LinearLayout) getChildAt(0);
    }

    /**
     * Centers the current view the best it can.
     */
    public void centerCurrentItem() {
        if (getMaxItemCount() == 0) {
            return;
        }

        int currentX = getScrollX();
        View targetChild;
        int currentChild = -1;

        do {
            currentChild++;
            targetChild = getLinearLayout().getChildAt(currentChild);
        } while (currentChild < getMaxItemCount() && targetChild.getLeft() < currentX);

        if (mActiveItem != currentChild) {
            mActiveItem = currentChild;
            scrollToActiveItem();
        }
    }

    /**
     * Scrolls the list view to the currently active child.
     */
    private void scrollToActiveItem() {
        int maxItemCount = getMaxItemCount();
        if (maxItemCount == 0) {
            return;
        }

        int targetItem = Math.min(maxItemCount - 1, mActiveItem);
        targetItem = Math.max(0, targetItem);

        mActiveItem = targetItem;

        // Scroll so that the target child is centered
        View targetView = getLinearLayout().getChildAt(targetItem);

        int targetLeft = targetView.getLeft();
        int childWidth = targetView.getRight() - targetLeft;

        int width = getWidth() - getPaddingLeft() - getPaddingRight();
        int targetScroll = targetLeft - ((width - childWidth) / 2);

        super.smoothScrollTo(targetScroll, 0);
    }

    /**
     * Sets the current item and centers it.
     * @param currentItem The new current item.
     */
    public void setCurrentItemAndCenter(int currentItem) {
        mActiveItem = currentItem;
        scrollToActiveItem();
    }
}
于 2013-09-19T12:57:15.700 回答