Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possibility of a Curved Gallery

Tags:

android

Is it possible to change the default arrangement of the Android Gallery? What i meant is can we make the Gallery in a curved path, where the images will be along the curved path and the same time it has all the properties of the Android gallery?

If possible, please tell me your ideas. All ideas are welcome.

Thanks & Regards, Sen

like image 236
Navaneeth Sen Avatar asked Sep 17 '10 04:09

Navaneeth Sen


1 Answers

Extend Gallery and override drawChild.

drawChild will be called for each child that needs to be drawn.

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

    final int left = child.getLeft();

    int adjustedXOrigin = left - (getWidth() / 2) + (child.getWidth()/2);

    int newtop = (int) (ellipseYOffset - Math.sqrt( ellipseMinor2 * (1 - ((Math.pow(adjustedXOrigin, 2)) / ellipseMajor2))));
    newtop -= (child.getHeight() / 2);

    if( newtop >= 0 )
    {
        child.layout(left, newtop, left + child.getWidth(), newtop + child.getHeight());
        return super.drawChild(canvas, child, drawingTime);
    }

    return true;
}

In onLayout I calculate ellipseYOffset. This centers the middle selected view vertically in the view, no matter the ellipse size.

ellipseYOffset = getMeasuredHeight() + (ellipseMinor - (getMeasuredHeight() / 2));

The "if (newtop >= 0 )" part is because the view were randomly getting drawn in weird places. This stopped that.

Edit: full code

There is some animation stuff you don't need, i just copied and pasted my class.

public class Carousel extends Gallery {

private static final float INITIAL_MINOR_RATIO = 0.75f;
private static final float INITIAL_MAJOR_RATIO = 1.0f;

private int mEllipseMajor;
private int mEllipseMinor;
private int mEllipseMajor2;
private int mEllipseMinor2;
private int mEllipseYOffset;

private Animation mGalleryAlphaOut;
private Animation mGalleryAlphaIn;

private OnAnimationEndListener mFadeInEndListener;
private OnAnimationEndListener mFadeOutEndListener;

private boolean mCustomEllipseDim = false;

private boolean mInfinite = true;

private int mXOff = 0;

private AnimationListener mFadeInAnimationListener = new AnimationListener() {
    public void onAnimationStart(Animation animation) {}
    public void onAnimationRepeat(Animation animation) {}
    public void onAnimationEnd(Animation animation) {
        if( mFadeInEndListener != null )
        {
            mFadeInEndListener.onAnimationEnd();
        }
    }
};

private AnimationListener mFadeOutAnimationListener = new AnimationListener() {
    public void onAnimationStart(Animation animation) {}
    public void onAnimationRepeat(Animation animation) {}
    public void onAnimationEnd(Animation animation) {
        if( mFadeOutEndListener != null )
        {
            mFadeOutEndListener.onAnimationEnd();
        }
    }
};

public Carousel(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

public Carousel(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public Carousel(Context context) {
    super(context);
    init();
}

private void init()
{
    setHorizontalFadingEdgeEnabled(false);
    setCallbackDuringFling(true);
    setUnselectedAlpha(1.0f);
    setHapticFeedbackEnabled(false);

    int dur = getResources().getInteger(R.integer.transition_dur);

    mGalleryAlphaOut = AnimationUtils.loadAnimation(getContext(), android.R.anim.fade_out);
    mGalleryAlphaOut.setFillAfter(true);
    mGalleryAlphaOut.setDuration(dur);
    mGalleryAlphaOut.setAnimationListener(mFadeOutAnimationListener);
    mGalleryAlphaIn = AnimationUtils.loadAnimation(getContext(), android.R.anim.fade_in);
    mGalleryAlphaIn.setFillAfter(true);
    mGalleryAlphaIn.setDuration(dur);
    mGalleryAlphaIn.setAnimationListener(mFadeInAnimationListener);
}

public int getEllipseMajor() {
    return mEllipseMajor;
}

public void setEllipseMajor(int ellipseMajor) {
    if( ellipseMajor == 0 )
    {
        mCustomEllipseDim = false;
    }
    this.mEllipseMajor = ellipseMajor;
}

public int getEllipseMinor() {
    return mEllipseMinor;
}

public void setEllipseMinor(int ellipseMinor) {
    if( ellipseMinor == 0 )
    {
        mCustomEllipseDim = false;
    }
    this.mEllipseMinor = ellipseMinor;
}

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    final int left = child.getLeft();
    final int childWidth = child.getWidth();
    final int childHeight = child.getHeight();

    int adjustedXOrigin = left - mXOff + (childWidth>>1);

    int newtop = (int) (mEllipseYOffset - Math.sqrt( mEllipseMinor2 * (1 - ((Math.pow(adjustedXOrigin, 2)) / mEllipseMajor2))));
    newtop -= (childHeight>>1);

    if( newtop >= 0 )
    {
        child.layout(left, newtop, left + childWidth, newtop + childHeight);
        return super.drawChild(canvas, child, drawingTime);
    }
    return true;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    if( !mCustomEllipseDim )
    {
        mEllipseMajor = (int) (getMeasuredWidth() * INITIAL_MAJOR_RATIO + 0.5f);
        mEllipseMinor = (int) (getMeasuredHeight() * INITIAL_MINOR_RATIO + 0.5f);
        mEllipseMajor2 = (int) Math.pow( mEllipseMajor, 2 );
        mEllipseMinor2 = (int) Math.pow( mEllipseMinor, 2 );
    }
    mEllipseYOffset = getMeasuredHeight() + (mEllipseMinor - (getMeasuredHeight() / 2));

    mXOff = (getWidth() / 2);
}

@Override
public void setAdapter(SpinnerAdapter adapter) {
    super.setAdapter(adapter);
    if( mInfinite )
    {
        resetPosition();
    }
}

public void resetPosition()
{
    int pos = Integer.MAX_VALUE / 2;
    if( getAdapter() != null && getAdapter().getClass() == CarouselAdapter.class )
    {
        int size = ((CarouselAdapter)getAdapter()).getList().size();
        if( size > 2 )
            pos = pos - (pos % ((CarouselAdapter)getAdapter()).getList().size());
        else
            pos = 0;
        setSelection(pos);
    }
}

public OnAnimationEndListener getFadeInEndListener() {
    return mFadeInEndListener;
}

public void setFadeInEndListener(OnAnimationEndListener fadeInEndListener) {
    this.mFadeInEndListener = fadeInEndListener;
}

public OnAnimationEndListener getFadeOutEndListener() {
    return mFadeOutEndListener;
}

public void setFadeOutEndListener(OnAnimationEndListener fadeOutEndListener) {
    this.mFadeOutEndListener = fadeOutEndListener;
}

public void fadeIn()
{
    startAnimation(mGalleryAlphaIn);
}

public void fadeOut()
{
    startAnimation(mGalleryAlphaOut);
}

public interface OnAnimationEndListener
{
    public abstract void onAnimationEnd();
}

//This disables the effect of a vehicle becoming focused when it is clicked.
@Override
public boolean onSingleTapUp(MotionEvent e) {
    if( getAdapter() != null )
    {
        if( pointToPosition((int)e.getX(), (int)e.getY()) != getSelectedItemPosition() )
            return true;
        else
            return super.onSingleTapUp(e);
    }
    else
        return true;
}
}
like image 197
khendricks Avatar answered Oct 22 '22 19:10

khendricks