画廊像中央图像缩放视图

时间:2013-09-19 07:56:57

标签: android

在这里,我需要一个像视图的图库,一次只能在屏幕上显示三个图像。在这里,中间的图像将比其两侧的其他两个图像大。

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

这里我不能使用gallery,因为它在android中被折旧了。

我可以使用this link上的代码在viewpager的帮助下创建一个类似于视图的图库。它一次只显示屏幕上的三个图像,符合我的一个要求。但我无法获得屏幕上可见的中央图像并进行缩放。虽然我能够在屏幕上显示点击的图像。

有人可以告诉我在哪里需要修改this代码以及我需要在其中添加的内容,以便从屏幕上显示的图像中获取中心的图像并进行缩放。

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

我也尝试过: -

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

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

提前感谢您的帮助。

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

P.S。对于想要完整代码的人,我已将其添加为答案,它也具有缩放功能。 在接受的答案中添加了几个。:)

2 个答案:

答案 0 :(得分: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);
}

您还可以动态设置图像的宽度,以便它们适合每个屏幕,只需要很少的额外工作。如果有人需要帮助,请告诉我,虽然我建议你自己尝试一下。

快乐的编码;)

答案 1 :(得分: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();
    }
}