Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gallery like view with center image zoom

Tags:

android

Here I need a gallery like view with only three images to be shown at a time on screen. In this the middle image will be larger than the two other images on its sides.

If the user scrolls the view next images will slide on screen as it does in gallery and at a time only three images will be shown out of which the center image should automatically zoom when it is shown on screen and remaining two should be smaller than it.

Here I can't use gallery because it is depreciated in android.

I was able to make a gallery like view with help of viewpager using code on this link. It shows only three images on screen at a time, which fits my one requirement. But i am not able to get the central image that is visible on screen and zoom it. Although I was able to get the clicked image on screen.

Can someone please tell me where do I need to modify this code and what I need to add in it to get the image that is in center from the images shown on screen and zoom it.

I know that there is no center image on screen according to viewpager and it is just showing three images on screen at a time because of modifications in code.

I have also tried:-

  • GridView with horizontal scroll
  • HorizontalScrollView with horizontal linear layout

but viewpager seems to be a better solution, because it stops the scrolling with only three items on screen because of viewpager's inherent properties.

and If someone knows any other method to achieve it, please tell me and I'll try it.

P.S. For anyone who wants the full code, I have added it as an answer, which has zoom capability also. Just few additions in accepted answer. :)

like image 726
DroidDev Avatar asked Sep 19 '13 07:09

DroidDev


2 Answers

Following code will help you to make a gallery like view which will have center lock. It responds to touch and swipe both. It shows three images on the screen at a time and the center image is zoomed.

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

}

In your xml add the horizontal scroll view like follow:-

<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>

Define a Linear layout in your activity.

LinearLayout imageGallery;

Then get it as follows:-

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

Now you have to add imageView to your LinearLayout. Here I assume that you have images in your drawable folder and you have made an array of ids of your images that you want to add to gallery. So you can do it via following method in your activity:-

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

You can also set the width of images dynamically, so that they fit every screen, with only little extra effort.

like image 117
DroidDev Avatar answered Oct 31 '22 22:10

DroidDev


Override setPrimaryItem in your ViewPager and make the center item bigger.

What was the issue with using a HorizontalScrollView with a LinearLayout? If it's centering you may be able to do something similar to this (assuming you've

/**
 * 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();
    }
}
like image 30
hamidp Avatar answered Oct 31 '22 21:10

hamidp