com.manojbhadane.view.CircleListView.java Source code

Java tutorial

Introduction

Here is the source code for com.manojbhadane.view.CircleListView.java

Source

/*
 ********************************************************************************
 * Copyright (c) 2012 Samsung Electronics, Inc.
 * All rights reserved.
 *
 * This software is a confidential and proprietary information of Samsung
 * Electronics, Inc. ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with the terms
 * of the license agreement you entered into with Samsung Electronics.
 ********************************************************************************
 */

package com.manojbhadane.view;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

import com.manojbhadane.semicircle.BuildConfig;

public class CircleListView extends ListView implements OnScrollListener {

    private static final int DEFAULT_SCROLL_DURATION = 200;
    private static final boolean DEBUG = BuildConfig.DEBUG && false;
    public static final int DEFAULT_SELECTION = Integer.MAX_VALUE / 2;
    private static final String TAG = CircleListView.class.getSimpleName();

    private boolean mIsForceCentering;
    private ViewModifier mViewModifier;
    private int mScrollDuration = DEFAULT_SCROLL_DURATION;
    private OnItemCenteredListener mOnItemCenteredListener;
    private final CenterRunnable mCenterRunnable = new CenterRunnable();

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

        super.setOnScrollListener(this);

        setOverscrollFooter(null);
        setOverscrollHeader(null);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        setSelection(DEFAULT_SELECTION);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        if (mViewModifier != null) {

            final int count = getChildCount();
            for (int i = 0; i < count; ++i) {
                View v = getChildAt(i);

                mViewModifier.applyToView(v, this);
            }
        }
    }

    /**
     * Sets the current {@link ViewModifier} for this list.
     * 
     * @param modifier
     *            implementation of the {@link ViewModifier} class
     * 
     * @see ViewModifier
     */
    public void setViewModifier(ViewModifier modifier) {
        mViewModifier = modifier;
    }

    /**
     * Sets the smooth scroll duration.
     * 
     * @param duration
     *            the number of milliseconds the scrolling animation will take
     */
    public void setScrollDuration(int duration) {
        mScrollDuration = duration;
    }

    /**
     * Sets the listener object that will be notified when the list centers on
     * an item.
     * 
     * @param listener
     *            the {@link OnItemCenteredListener} implementation
     */
    public void setOnItemCenteredListener(OnItemCenteredListener listener) {
        mOnItemCenteredListener = listener;
    }

    /**
     * Smoothly scrolls the {@link CircleListView} so the {@link View} v is in
     * the middle.
     * 
     * @param v
     *            the {@link View} that should be in the center after the scroll
     * @param scrollDuration
     *            how long will the scroll take
     */
    public void smoothScrollToView(View v) {
        final float y = v.getY() + v.getHeight() * 0.5f;
        final float halfHeight = getHeight() * 0.5f;
        final int distance = (int) (y - halfHeight);

        smoothScrollBy(distance, mScrollDuration);
    }

    @Override
    public void setOnScrollListener(OnScrollListener l) {
        throw new UnsupportedOperationException();
    }

    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {

            if (!mIsForceCentering) {
                // Start centering the view

                mIsForceCentering = true;

                final View childView = findViewAtCenter();

                if (childView != null) {
                    if (DEBUG) {
                        //                  TextView tv = (TextView) childView.findViewById(R.id.label_app_name);
                        //                  Log.d(TAG, "Application in center: " + tv.getText().toString());
                    }

                    if (mOnItemCenteredListener != null) {
                        mOnItemCenteredListener.onItemCentered(childView);
                    }

                    mCenterRunnable.setView(childView);
                    ViewCompat.postOnAnimation(this, mCenterRunnable);
                }
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        removeCallbacks(mCenterRunnable);

        mIsForceCentering = false;

        return super.onTouchEvent(ev);
    }

    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

    /**
     * Finds a View located at the specified point.
     * 
     * @param x
     *            x-coordinate of the point
     * @param y
     *            y-coordinate of the point
     * @return {@link View} located at (x, y) or <code>null</code> if not found
     */
    public View findViewAt(int x, int y) {
        final int count = getChildCount();
        for (int i = 0; i < count; ++i) {
            final View v = getChildAt(i);
            final int x0 = v.getLeft();
            final int y0 = v.getTop();
            final int x1 = v.getWidth() - x0;
            final int y1 = v.getHeight() + y0;

            if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
                return v;
            }
        }

        return null;
    }

    /**
     * Finds a {@link View} located in the center of the {@link CircleListView}.
     * 
     * @return the {@link View} at the center of the {@link CircleListView}
     */
    public View findViewAtCenter() {
        return findViewAt(0, getHeight() / 2);
    }

    public class CenterRunnable implements Runnable {

        private View mView;

        public void setView(View v) {
            mView = v;
        }

        public void run() {
            smoothScrollToView(mView);

            mIsForceCentering = true;
        }
    }

    /**
     * Handles the event occurring when the list centers on an item.
     * 
     * @see CircleListView#setOnItemCenteredListener(OnItemCenteredListener)
     */
    public interface OnItemCenteredListener {
        public void onItemCentered(View v);
    }
}