Monday, January 7, 2013

Timer Whell like Iphone


                                   Timer Whell like as Iphone
Timer selection wheel like as in Iphone scroll wheel view.
copy all these files and test the application you fee; beret,


layout_bg.xml:
-------------

<?xml version="1.0" encoding="utf-8"?>

<!-- 
    Android Wheel Control.
    http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html

    Copyright 2010 Yuri Kanivets
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<shape xmlns:android="http://schemas.android.com/apk/res/android">
        <gradient
                android:startColor="#FF000000"
                android:centerColor="#FF000000"
                android:endColor="#FF777777"
                android:angle="90" />
</shape>


wheel_bg.xml:
------------


<!-- 
    Android Wheel Control.
    http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
   
    Copyright 2010 Yuri Kanivets
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient android:startColor="#333" android:centerColor="#DDD" android:endColor="#333" android:angle="90"/>
<stroke android:width="1dp" android:color="#FF333333"/>
</shape>
</item>
<item android:left="4dp" android:right="4dp" android:top="1dp" android:bottom="1dp">
<shape android:shape="rectangle">
<gradient android:startColor="#AAA" android:centerColor="#FFF" android:endColor="#AAA" android:angle="90"/>
</shape>
</item>
</layer-list>


wheel_val.xml:
-------------


<?xml version="1.0" encoding="utf-8"?>

<!--
    Android Wheel Control.
    http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
 
    Copyright 2010 Yuri Kanivets
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<shape xmlns:android="http://schemas.android.com/apk/res/android">
        <gradient
                android:startColor="#70222222"
                android:centerColor="#70222222"
                android:endColor="#70EEEEEE"
                android:angle="90" />

        <stroke android:width="1dp" android:color="#70333333" />
</shape>



time_layout.xml:
----------------


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/timer_lt"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/layout_bg"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:paddingLeft="12dp"
            android:paddingRight="12dp"
            android:paddingTop="20dp" >

            <kankan.wheel.WheelView
                android:id="@+id/hour"
                android:layout_width="140dp"
                android:layout_height="wrap_content" />

            <kankan.wheel.WheelView
                android:id="@+id/mins"
                android:layout_width="140dp"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        android:layout_above="@+id/timer_lt"
        android:background="#000000"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:text="set timer"
            android:textColor="@android:color/white"
            android:textSize="18dp" />
    </RelativeLayout>

</RelativeLayout>


AndroidManifest.xml:
------------------

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kankan.wheel"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".TimeActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>



WheelView.java:
--------------


/*
 *  Android Wheel Control.
 *  https://code.google.com/p/android-wheel/
 *
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import java.util.LinkedList;
import java.util.List;

import kankan.wheel.R;
import kankan.wheel.WheelViewAdapter;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;

/**
 * Numeric wheel view.
 *
 * @author Yuri Kanivets
 */
public class WheelView extends View {

/** Top and bottom shadows colors */
private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111,
0x00AAAAAA, 0x00AAAAAA };

/** Top and bottom items offset (to hide that) */
private static final int ITEM_OFFSET_PERCENT = 10;

/** Left and right padding value */
private static final int PADDING = 10;

/** Default count of visible items */
private static final int DEF_VISIBLE_ITEMS = 5;

// Wheel Values
private int currentItem = 0;

// Count of visible items
private int visibleItems = DEF_VISIBLE_ITEMS;

// Item height
private int itemHeight = 0;

// Center Line
private Drawable centerDrawable;

// Shadows drawables
private GradientDrawable topShadow;
private GradientDrawable bottomShadow;

// Scrolling
private WheelScroller scroller;
    private boolean isScrollingPerformed;
    private int scrollingOffset;

// Cyclic
boolean isCyclic = false;

// Items layout
private LinearLayout itemsLayout;

// The number of first item in layout
private int firstItem;

// View adapter
private WheelViewAdapter viewAdapter;

// Recycle
private WheelRecycle recycle = new WheelRecycle(this);

// Listeners
private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();
    private List<OnWheelClickedListener> clickingListeners = new LinkedList<OnWheelClickedListener>();

/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initData(context);
}

/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs) {
super(context, attrs);
initData(context);
}

/**
* Constructor
*/
public WheelView(Context context) {
super(context);
initData(context);
}

/**
* Initializes class data
* @param context the context
*/
private void initData(Context context) {
   scroller = new WheelScroller(getContext(), scrollingListener);
}

// Scrolling listener
WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() {
        public void onStarted() {
            isScrollingPerformed = true;
            notifyScrollingListenersAboutStart();
        }
       
        public void onScroll(int distance) {
            doScroll(distance);
           
            int height = getHeight();
            if (scrollingOffset > height) {
                scrollingOffset = height;
                scroller.stopScrolling();
            } else if (scrollingOffset < -height) {
                scrollingOffset = -height;
                scroller.stopScrolling();
            }
        }
       
        public void onFinished() {
            if (isScrollingPerformed) {
                notifyScrollingListenersAboutEnd();
                isScrollingPerformed = false;
            }
           
            scrollingOffset = 0;
            invalidate();
        }

        public void onJustify() {
            if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) {
                scroller.scroll(scrollingOffset, 0);
            }
        }
    };

/**
* Set the the specified scrolling interpolator
* @param interpolator the interpolator
*/
public void setInterpolator(Interpolator interpolator) {
scroller.setInterpolator(interpolator);
}

/**
* Gets count of visible items
*
* @return the count of visible items
*/
public int getVisibleItems() {
return visibleItems;
}

/**
* Sets the desired count of visible items.
* Actual amount of visible items depends on wheel layout parameters.
* To apply changes and rebuild view call measure().
*
* @param count the desired count for visible items
*/
public void setVisibleItems(int count) {
visibleItems = count;
}

/**
* Gets view adapter
* @return the view adapter
*/
public WheelViewAdapter getViewAdapter() {
return viewAdapter;
}

// Adapter listener
    private DataSetObserver dataObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            invalidateWheel(false);
        }

        @Override
        public void onInvalidated() {
            invalidateWheel(true);
        }
    };

/**
* Sets view adapter. Usually new adapters contain different views, so
* it needs to rebuild view by calling measure().
*
* @param viewAdapter the view adapter
*/
public void setViewAdapter(WheelViewAdapter viewAdapter) {
   if (this.viewAdapter != null) {
       this.viewAdapter.unregisterDataSetObserver(dataObserver);
   }
        this.viewAdapter = viewAdapter;
        if (this.viewAdapter != null) {
            this.viewAdapter.registerDataSetObserver(dataObserver);
        }
       
        invalidateWheel(true);
}

/**
* Adds wheel changing listener
* @param listener the listener
*/
public void addChangingListener(OnWheelChangedListener listener) {
changingListeners.add(listener);
}

/**
* Removes wheel changing listener
* @param listener the listener
*/
public void removeChangingListener(OnWheelChangedListener listener) {
changingListeners.remove(listener);
}

/**
* Notifies changing listeners
* @param oldValue the old wheel value
* @param newValue the new wheel value
*/
protected void notifyChangingListeners(int oldValue, int newValue) {
for (OnWheelChangedListener listener : changingListeners) {
listener.onChanged(this, oldValue, newValue);
}
}

/**
* Adds wheel scrolling listener
* @param listener the listener
*/
public void addScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.add(listener);
}

/**
* Removes wheel scrolling listener
* @param listener the listener
*/
public void removeScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.remove(listener);
}

/**
* Notifies listeners about starting scrolling
*/
protected void notifyScrollingListenersAboutStart() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingStarted(this);
}
}

/**
* Notifies listeners about ending scrolling
*/
protected void notifyScrollingListenersAboutEnd() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingFinished(this);
}
}

    /**
     * Adds wheel clicking listener
     * @param listener the listener
     */
    public void addClickingListener(OnWheelClickedListener listener) {
        clickingListeners.add(listener);
    }

    /**
     * Removes wheel clicking listener
     * @param listener the listener
     */
    public void removeClickingListener(OnWheelClickedListener listener) {
        clickingListeners.remove(listener);
    }
   
    /**
     * Notifies listeners about clicking
     */
    protected void notifyClickListenersAboutClick(int item) {
        for (OnWheelClickedListener listener : clickingListeners) {
            listener.onItemClicked(this, item);
        }
    }

/**
* Gets current value
*
* @return the current value
*/
public int getCurrentItem() {
return currentItem;
}

/**
* Sets the current item. Does nothing when index is wrong.
*
* @param index the item index
* @param animated the animation flag
*/
public void setCurrentItem(int index, boolean animated) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return; // throw?
}

int itemCount = viewAdapter.getItemsCount();
if (index < 0 || index >= itemCount) {
if (isCyclic) {
while (index < 0) {
index += itemCount;
}
index %= itemCount;
} else{
return; // throw?
}
}
if (index != currentItem) {
if (animated) {
   int itemsToScroll = index - currentItem;
   if (isCyclic) {
       int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem);
       if (scroll < Math.abs(itemsToScroll)) {
           itemsToScroll = itemsToScroll < 0 ? scroll : -scroll;
       }
   }
scroll(itemsToScroll, 0);
} else {
scrollingOffset = 0;

int old = currentItem;
currentItem = index;

notifyChangingListeners(old, currentItem);

invalidate();
}
}
}

/**
* Sets the current item w/o animation. Does nothing when index is wrong.
*
* @param index the item index
*/
public void setCurrentItem(int index) {
setCurrentItem(index, false);
}

/**
* Tests if wheel is cyclic. That means before the 1st item there is shown the last one
* @return true if wheel is cyclic
*/
public boolean isCyclic() {
return isCyclic;
}

/**
* Set wheel cyclic flag
* @param isCyclic the flag to set
*/
public void setCyclic(boolean isCyclic) {
this.isCyclic = isCyclic;
invalidateWheel(false);
}

/**
* Invalidates wheel
* @param clearCaches if true then cached views will be clear
*/
    public void invalidateWheel(boolean clearCaches) {
        if (clearCaches) {
            recycle.clearAll();
            if (itemsLayout != null) {
                itemsLayout.removeAllViews();
            }
            scrollingOffset = 0;
        } else if (itemsLayout != null) {
            // cache all items
       recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());        
        }
       
        invalidate();
}

/**
* Initializes resources
*/
private void initResourcesIfNecessary() {
if (centerDrawable == null) {
centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val);
}

if (topShadow == null) {
topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
}

if (bottomShadow == null) {
bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
}

setBackgroundResource(R.drawable.wheel_bg);
}

/**
* Calculates desired height for layout
*
* @param layout
*            the source layout
* @return the desired layout height
*/
private int getDesiredHeight(LinearLayout layout) {
if (layout != null && layout.getChildAt(0) != null) {
itemHeight = layout.getChildAt(0).getMeasuredHeight();
}

int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50;

return Math.max(desired, getSuggestedMinimumHeight());
}

/**
* Returns height of wheel item
* @return the item height
*/
private int getItemHeight() {
if (itemHeight != 0) {
return itemHeight;
}

if (itemsLayout != null && itemsLayout.getChildAt(0) != null) {
itemHeight = itemsLayout.getChildAt(0).getHeight();
return itemHeight;
}

return getHeight() / visibleItems;
}

/**
* Calculates control width and creates text layouts
* @param widthSize the input layout width
* @param mode the layout mode
* @return the calculated control width
*/
private int calculateLayoutWidth(int widthSize, int mode) {
initResourcesIfNecessary();

// TODO: make it static
itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
   itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED),
               MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int width = itemsLayout.getMeasuredWidth();

if (mode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width += 2 * PADDING;

// Check against our minimum width
width = Math.max(width, getSuggestedMinimumWidth());

if (mode == MeasureSpec.AT_MOST && widthSize < width) {
width = widthSize;
}
}

        itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

return width;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

buildViewForMeasuring();

int width = calculateLayoutWidth(widthSize, widthMode);

int height;
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = getDesiredHeight(itemsLayout);

if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, heightSize);
}
}

setMeasuredDimension(width, height);
}

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    layout(r - l, b - t);
    }

    /**
     * Sets layouts width and height
     * @param width the layout width
     * @param height the layout height
     */
    private void layout(int width, int height) {
int itemsWidth = width - 2 * PADDING;

itemsLayout.layout(0, 0, itemsWidth, height);
    }

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

if (viewAdapter != null && viewAdapter.getItemsCount() > 0) {
       updateView();

       drawItems(canvas);
       drawCenterRect(canvas);
}

        drawShadows(canvas);
}

/**
* Draws shadows on top and bottom of control
* @param canvas the canvas for drawing
*/
private void drawShadows(Canvas canvas) {
int height = (int)(1.5 * getItemHeight());
topShadow.setBounds(0, 0, getWidth(), height);
topShadow.draw(canvas);

bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
bottomShadow.draw(canvas);
}

/**
* Draws items
* @param canvas the canvas for drawing
*/
private void drawItems(Canvas canvas) {
canvas.save();

int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2;
canvas.translate(PADDING, - top + scrollingOffset);

itemsLayout.draw(canvas);

canvas.restore();
}

/**
* Draws rect for current value
* @param canvas the canvas for drawing
*/
private void drawCenterRect(Canvas canvas) {
int center = getHeight() / 2;
int offset = (int) (getItemHeight() / 2 * 1.2);
centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
centerDrawable.draw(canvas);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled() || getViewAdapter() == null) {
return true;
}

switch (event.getAction()) {
   case MotionEvent.ACTION_MOVE:
       if (getParent() != null) {
           getParent().requestDisallowInterceptTouchEvent(true);
       }
       break;
     
   case MotionEvent.ACTION_UP:
       if (!isScrollingPerformed) {
           int distance = (int) event.getY() - getHeight() / 2;
           if (distance > 0) {
               distance += getItemHeight() / 2;
           } else {
                        distance -= getItemHeight() / 2;
           }
           int items = distance / getItemHeight();
           if (items != 0 && isValidItemIndex(currentItem + items)) {
                   notifyClickListenersAboutClick(currentItem + items);
           }
       }
       break;
}

return scroller.onTouchEvent(event);
}

/**
* Scrolls the wheel
* @param delta the scrolling value
*/
private void doScroll(int delta) {
scrollingOffset += delta;

int itemHeight = getItemHeight();
int count = scrollingOffset / itemHeight;

int pos = currentItem - count;
int itemCount = viewAdapter.getItemsCount();

   int fixPos = scrollingOffset % itemHeight;
   if (Math.abs(fixPos) <= itemHeight / 2) {
       fixPos = 0;
   }
if (isCyclic && itemCount > 0) {
   if (fixPos > 0) {
       pos--;
                count++;
   } else if (fixPos < 0) {
       pos++;
       count--;
   }
// fix position by rotating
while (pos < 0) {
pos += itemCount;
}
pos %= itemCount;
} else {
//
if (pos < 0) {
count = currentItem;
pos = 0;
} else if (pos >= itemCount) {
count = currentItem - itemCount + 1;
pos = itemCount - 1;
} else if (pos > 0 && fixPos > 0) {
                pos--;
                count++;
            } else if (pos < itemCount - 1 && fixPos < 0) {
                pos++;
                count--;
            }
}

int offset = scrollingOffset;
if (pos != currentItem) {
setCurrentItem(pos, false);
} else {
invalidate();
}

// update offset
scrollingOffset = offset - count * itemHeight;
if (scrollingOffset > getHeight()) {
scrollingOffset = scrollingOffset % getHeight() + getHeight();
}
}

/**
* Scroll the wheel
* @param itemsToSkip items to scroll
* @param time scrolling duration
*/
public void scroll(int itemsToScroll, int time) {
int distance = itemsToScroll * getItemHeight() - scrollingOffset;
        scroller.scroll(distance, time);
}

/**
* Calculates range for wheel items
* @return the items range
*/
private ItemsRange getItemsRange() {
        if (getItemHeight() == 0) {
            return null;
        }
       
int first = currentItem;
int count = 1;

while (count * getItemHeight() < getHeight()) {
first--;
count += 2; // top + bottom items
}

if (scrollingOffset != 0) {
if (scrollingOffset > 0) {
first--;
}
count++;

// process empty items above the first or below the second
int emptyItems = scrollingOffset / getItemHeight();
first -= emptyItems;
count += Math.asin(emptyItems);
}
return new ItemsRange(first, count);
}

/**
* Rebuilds wheel items if necessary. Caches all unused items.
*
* @return true if items are rebuilt
*/
private boolean rebuildItems() {
boolean updated = false;
ItemsRange range = getItemsRange();
if (itemsLayout != null) {
int first = recycle.recycleItems(itemsLayout, firstItem, range);
updated = firstItem != first;
firstItem = first;
} else {
createItemsLayout();
updated = true;
}

if (!updated) {
updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount();
}

if (firstItem > range.getFirst() && firstItem <= range.getLast()) {
for (int i = firstItem - 1; i >= range.getFirst(); i--) {
if (!addViewItem(i, true)) {
   break;
}
firstItem = i;
}
} else {
   firstItem = range.getFirst();
}

int first = firstItem;
for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) {
if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) {
   first++;
}
}
firstItem = first;

return updated;
}

/**
* Updates view. Rebuilds items and label if necessary, recalculate items sizes.
*/
private void updateView() {
if (rebuildItems()) {
calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
layout(getWidth(), getHeight());
}
}

/**
* Creates item layouts if necessary
*/
private void createItemsLayout() {
if (itemsLayout == null) {
itemsLayout = new LinearLayout(getContext());
itemsLayout.setOrientation(LinearLayout.VERTICAL);
}
}

/**
* Builds view for measuring
*/
private void buildViewForMeasuring() {
// clear all items
if (itemsLayout != null) {
recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
} else {
createItemsLayout();
}

// add views
int addItems = visibleItems / 2;
for (int i = currentItem + addItems; i >= currentItem - addItems; i--) {
if (addViewItem(i, true)) {
   firstItem = i;
}
}
}

/**
* Adds view for item to items layout
* @param index the item index
* @param first the flag indicates if view should be first
* @return true if corresponding item exists and is added
*/
private boolean addViewItem(int index, boolean first) {
View view = getItemView(index);
if (view != null) {
if (first) {
itemsLayout.addView(view, 0);
} else {
itemsLayout.addView(view);
}

return true;
}

return false;
}

/**
* Checks whether intem index is valid
* @param index the item index
* @return true if item index is not out of bounds or the wheel is cyclic
*/
private boolean isValidItemIndex(int index) {
   return viewAdapter != null && viewAdapter.getItemsCount() > 0 &&
       (isCyclic || index >= 0 && index < viewAdapter.getItemsCount());
}

/**
* Returns view for specified item
* @param index the item index
* @return item view or empty view if index is out of bounds
*/
    private View getItemView(int index) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return null;
}
int count = viewAdapter.getItemsCount();
if (!isValidItemIndex(index)) {
return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout);
} else {
while (index < 0) {
index = count + index;
}
}

index %= count;
return viewAdapter.getItem(index, recycle.getItem(), itemsLayout);
}

/**
* Stops scrolling
*/
public void stopScrolling() {
   scroller.stopScrolling();
}
}



WheelViewAdapter.java:
---------------------
/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;

/**
 * Wheel items adapter interface
 */
public interface WheelViewAdapter {
        /**
         * Gets items count
         * @return the count of wheel items
         */
        public int getItemsCount();
       
        /**
         * Get a View that displays the data at the specified position in the data set
         *
         * @param index the item index
         * @param convertView the old view to reuse if possible
         * @param parent the parent that this view will eventually be attached to
         * @return the wheel item View
         */
        public View getItem(int index, View convertView, ViewGroup parent);

        /**
         * Get a View that displays an empty wheel item placed before the first or after
         * the last wheel item.
         *
         * @param convertView the old view to reuse if possible
     * @param parent the parent that this view will eventually be attached to
         * @return the empty item View
         */
        public View getEmptyItem(View convertView, ViewGroup parent);
       
        /**
         * Register an observer that is called when changes happen to the data used by this adapter.
         * @param observer the observer to be registered
         */
        public void registerDataSetObserver(DataSetObserver observer);
       
        /**
         * Unregister an observer that has previously been registered
         * @param observer the observer to be unregistered
         */
        void unregisterDataSetObserver (DataSetObserver observer);
}




WheelScroller.java:
------------------


/*
 *  Android Wheel Control.
 *  https://code.google.com/p/android-wheel/
 *
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.animation.Interpolator;
import android.widget.Scroller;

/**
 * Scroller class handles scrolling events and updates the
 */
public class WheelScroller {
    /**
     * Scrolling listener interface
     */
    public interface ScrollingListener {
        /**
         * Scrolling callback called when scrolling is performed.
         * @param distance the distance to scroll
         */
        void onScroll(int distance);

        /**
         * Starting callback called when scrolling is started
         */
        void onStarted();
       
        /**
         * Finishing callback called after justifying
         */
        void onFinished();
       
        /**
         * Justifying callback called to justify a view when scrolling is ended
         */
        void onJustify();
    }
   
    /** Scrolling duration */
    private static final int SCROLLING_DURATION = 400;

    /** Minimum delta for scrolling */
    public static final int MIN_DELTA_FOR_SCROLLING = 1;

    // Listener
    private ScrollingListener listener;
   
    // Context
    private Context context;
   
    // Scrolling
    private GestureDetector gestureDetector;
    private Scroller scroller;
    private int lastScrollY;
    private float lastTouchedY;
    private boolean isScrollingPerformed;

    /**
     * Constructor
     * @param context the current context
     * @param listener the scrolling listener
     */
    public WheelScroller(Context context, ScrollingListener listener) {
        gestureDetector = new GestureDetector(context, gestureListener);
        gestureDetector.setIsLongpressEnabled(false);
       
        scroller = new Scroller(context);

        this.listener = listener;
        this.context = context;
    }
   
    /**
     * Set the the specified scrolling interpolator
     * @param interpolator the interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        scroller.forceFinished(true);
        scroller = new Scroller(context, interpolator);
    }
   
    /**
     * Scroll the wheel
     * @param distance the scrolling distance
     * @param time the scrolling duration
     */
    public void scroll(int distance, int time) {
        scroller.forceFinished(true);

        lastScrollY = 0;
       
        scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION);
        setNextMessage(MESSAGE_SCROLL);
       
        startScrolling();
    }
 
    /**
     * Stops scrolling
     */
    public void stopScrolling() {
        scroller.forceFinished(true);
    }
   
    /**
     * Handles Touch event
     * @param event the motion event
     * @return
     */
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastTouchedY = event.getY();
                scroller.forceFinished(true);
                clearMessages();
                break;
   
            case MotionEvent.ACTION_MOVE:
                // perform scrolling
                int distanceY = (int)(event.getY() - lastTouchedY);
                if (distanceY != 0) {
                    startScrolling();
                    listener.onScroll(distanceY);
                    lastTouchedY = event.getY();
                }
                break;
        }
       
        if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
            justify();
        }

        return true;
    }
   
    // gesture listener
    private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            // Do scrolling in onTouchEvent() since onScroll() are not call immediately
            //  when user touch and move the wheel
            return true;
        }
       
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            lastScrollY = 0;
            final int maxY = 0x7FFFFFFF;
            final int minY = -maxY;
            scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY);
            setNextMessage(MESSAGE_SCROLL);
            return true;
        }
    };

    // Messages
    private final int MESSAGE_SCROLL = 0;
    private final int MESSAGE_JUSTIFY = 1;
   
    /**
     * Set next message to queue. Clears queue before.
     *
     * @param message the message to set
     */
    private void setNextMessage(int message) {
        clearMessages();
        animationHandler.sendEmptyMessage(message);
    }

    /**
     * Clears messages from queue
     */
    private void clearMessages() {
        animationHandler.removeMessages(MESSAGE_SCROLL);
        animationHandler.removeMessages(MESSAGE_JUSTIFY);
    }
   
    // animation handler
    private Handler animationHandler = new Handler() {
        public void handleMessage(Message msg) {
            scroller.computeScrollOffset();
            int currY = scroller.getCurrY();
            int delta = lastScrollY - currY;
            lastScrollY = currY;
            if (delta != 0) {
                listener.onScroll(delta);
            }
           
            // scrolling is not finished when it comes to final Y
            // so, finish it manually
            if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
                currY = scroller.getFinalY();
                scroller.forceFinished(true);
            }
            if (!scroller.isFinished()) {
                animationHandler.sendEmptyMessage(msg.what);
            } else if (msg.what == MESSAGE_SCROLL) {
                justify();
            } else {
                finishScrolling();
            }
        }
    };
   
    /**
     * Justifies wheel
     */
    private void justify() {
        listener.onJustify();
        setNextMessage(MESSAGE_JUSTIFY);
    }

    /**
     * Starts scrolling
     */
    private void startScrolling() {
        if (!isScrollingPerformed) {
            isScrollingPerformed = true;
            listener.onStarted();
        }
    }

    /**
     * Finishes scrolling
     */
    void finishScrolling() {
        if (isScrollingPerformed) {
            listener.onFinished();
            isScrollingPerformed = false;
        }
    }
}



WheelRecycle.java:
-----------------

/*
 *  Android Wheel Control.
 *  https://code.google.com/p/android-wheel/
 *
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import java.util.LinkedList;
import java.util.List;

import android.view.View;
import android.widget.LinearLayout;

/**
 * Recycle stores wheel items to reuse.
 */
public class WheelRecycle {
        // Cached items
        private List<View> items;
       
        // Cached empty items
        private List<View> emptyItems;
       
        // Wheel view
        private WheelView wheel;
       
        /**
         * Constructor
         * @param wheel the wheel view
         */
        public WheelRecycle(WheelView wheel) {
                this.wheel = wheel;
        }

        /**
         * Recycles items from specified layout.
         * There are saved only items not included to specified range.
         * All the cached items are removed from original layout.
         *
         * @param layout the layout containing items to be cached
         * @param firstItem the number of first item in layout
         * @param range the range of current wheel items
         * @return the new value of first item number
         */
        public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) {
                int index = firstItem;
                for (int i = 0; i < layout.getChildCount();) {
                        if (!range.contains(index)) {
                                recycleView(layout.getChildAt(i), index);
                                layout.removeViewAt(i);
                                if (i == 0) { // first item
                                        firstItem++;
                                }
                        } else {
                                i++; // go to next item
                        }
                        index++;
                }
                return firstItem;
        }
       
        /**
         * Gets item view
         * @return the cached view
         */
        public View getItem() {
                return getCachedView(items);
        }

        /**
         * Gets empty item view
         * @return the cached empty view
         */
        public View getEmptyItem() {
                return getCachedView(emptyItems);
        }
       
        /**
         * Clears all views
         */
        public void clearAll() {
                if (items != null) {
                        items.clear();
                }
                if (emptyItems != null) {
                        emptyItems.clear();
                }
        }

        /**
         * Adds view to specified cache. Creates a cache list if it is null.
         * @param view the view to be cached
         * @param cache the cache list
         * @return the cache list
         */
        private List<View> addView(View view, List<View> cache) {
                if (cache == null) {
                        cache = new LinkedList<View>();
                }
               
                cache.add(view);
                return cache;
        }

        /**
         * Adds view to cache. Determines view type (item view or empty one) by index.
         * @param view the view to be cached
         * @param index the index of view
         */
        private void recycleView(View view, int index) {
                int count = wheel.getViewAdapter().getItemsCount();

                if ((index < 0 || index >= count) && !wheel.isCyclic()) {
                        // empty view
                        emptyItems = addView(view, emptyItems);
                } else {
                        while (index < 0) {
                                index = count + index;
                        }
                        index %= count;
                        items = addView(view, items);
                }
        }
       
        /**
         * Gets view from specified cache.
         * @param cache the cache
         * @return the first view from cache.
         */
        private View getCachedView(List<View> cache) {
                if (cache != null && cache.size() > 0) {
                        View view = cache.get(0);
                        cache.remove(0);
                        return view;
                }
                return null;
        }

}


OnWheelScrollListener.java:
--------------------------

/*
 *  Copyright 2010 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

/**
 * Wheel scrolled listener interface.
 */
public interface OnWheelScrollListener {
        /**
         * Callback method to be invoked when scrolling started.
         * @param wheel the wheel view whose state has changed.
         */
        void onScrollingStarted(WheelView wheel);
       
        /**
         * Callback method to be invoked when scrolling ended.
         * @param wheel the wheel view whose state has changed.
         */
        void onScrollingFinished(WheelView wheel);
}



OnWheelClickedListener.java:
---------------------------


/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

/**
 * Wheel clicked listener interface.
 * <p>The onItemClicked() method is called whenever a wheel item is clicked
 * <li> New Wheel position is set
 * <li> Wheel view is scrolled
 */
public interface OnWheelClickedListener {
    /**
     * Callback method to be invoked when current item clicked
     * @param wheel the wheel view
     * @param itemIndex the index of clicked item
     */
    void onItemClicked(WheelView wheel, int itemIndex);
}


OnWheelChangedListener.java:
---------------------------

/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

/**
 * Wheel changed listener interface.
 * <p>The onChanged() method is called whenever current wheel positions is changed:
 * <li> New Wheel position is set
 * <li> Wheel view is scrolled
 */
public interface OnWheelChangedListener {
        /**
         * Callback method to be invoked when current item changed
         * @param wheel the wheel view whose state has changed
         * @param oldValue the old value of current item
         * @param newValue the new value of current item
         */
        void onChanged(WheelView wheel, int oldValue, int newValue);
}



NumericWheelAdapter.java:
------------------------

/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import android.content.Context;

/**
 * Numeric Wheel adapter.
 */
public class NumericWheelAdapter extends AbstractWheelTextAdapter {
   
    /** The default min value */
    public static final int DEFAULT_MAX_VALUE = 9;

    /** The default max value */
    private static final int DEFAULT_MIN_VALUE = 0;
   
    // Values
    private int minValue;
    private int maxValue;
   
    // format
    private String format;
   
    /**
     * Constructor
     * @param context the current context
     */
    public NumericWheelAdapter(Context context) {
        this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE);
    }

    /**
     * Constructor
     * @param context the current context
     * @param minValue the wheel min value
     * @param maxValue the wheel max value
     */
    public NumericWheelAdapter(Context context, int minValue, int maxValue) {
        this(context, minValue, maxValue, null);
    }

    /**
     * Constructor
     * @param context the current context
     * @param minValue the wheel min value
     * @param maxValue the wheel max value
     * @param format the format string
     */
    public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) {
        super(context);
       
        this.minValue = minValue;
        this.maxValue = maxValue;
        this.format = format;
    }

    @Override
    public CharSequence getItemText(int index) {
        if (index >= 0 && index < getItemsCount()) {
            int value = minValue + index;
            return format != null ? String.format(format, value) : Integer.toString(value);
        }
        return null;
    }

    @Override
    public int getItemsCount() {
        return maxValue - minValue + 1;
    }  
}



ItemsRange.java:
---------------

/*
 *  Android Wheel Control.
 *  https://code.google.com/p/android-wheel/
 *
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

/**
 * Range for visible items.
 */
public class ItemsRange {
        // First item number
        private int first;
       
        // Items count
        private int count;

        /**
         * Default constructor. Creates an empty range
         */
    public ItemsRange() {
        this(0, 0);
    }
   
        /**
         * Constructor
         * @param first the number of first item
         * @param count the count of items
         */
        public ItemsRange(int first, int count) {
                this.first = first;
                this.count = count;
        }
       
        /**
         * Gets number of  first item
         * @return the number of the first item
         */
        public int getFirst() {
                return first;
        }
       
        /**
         * Gets number of last item
         * @return the number of last item
         */
        public int getLast() {
                return getFirst() + getCount() - 1;
        }
       
        /**
         * Get items count
         * @return the count of items
         */
        public int getCount() {
                return count;
        }
       
        /**
         * Tests whether item is contained by range
         * @param index the item number
         * @return true if item is contained
         */
        public boolean contains(int index) {
                return index >= getFirst() && index <= getLast();
        }
}



AbstractWheelTextAdapter.java:
-----------------------------

/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package kankan.wheel;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Abstract wheel adapter provides common functionality for adapters.
 */
public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter {
   
    /** Text view resource. Used as a default view for adapter. */
    public static final int TEXT_VIEW_ITEM_RESOURCE = -1;
   
    /** No resource constant. */
    protected static final int NO_RESOURCE = 0;
   
    /** Default text color */
    public static final int DEFAULT_TEXT_COLOR = 0xFF101010;
   
    /** Default text color */
    public static final int LABEL_COLOR = 0xFF700070;
   
    /** Default text size */
    public static final int DEFAULT_TEXT_SIZE = 24;
   
    // Text settings
    private int textColor = DEFAULT_TEXT_COLOR;
    private int textSize = DEFAULT_TEXT_SIZE;
   
    // Current context
    protected Context context;
    // Layout inflater
    protected LayoutInflater inflater;
   
    // Items resources
    protected int itemResourceId;
    protected int itemTextResourceId;
   
    // Empty items resources
    protected int emptyItemResourceId;
       
    /**
     * Constructor
     * @param context the current context
     */
    protected AbstractWheelTextAdapter(Context context) {
        this(context, TEXT_VIEW_ITEM_RESOURCE);
    }

    /**
     * Constructor
     * @param context the current context
     * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
     */
    protected AbstractWheelTextAdapter(Context context, int itemResource) {
        this(context, itemResource, NO_RESOURCE);
    }
   
    /**
     * Constructor
     * @param context the current context
     * @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
     * @param itemTextResource the resource ID for a text view in the item layout
     */
    protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) {
        this.context = context;
        itemResourceId = itemResource;
        itemTextResourceId = itemTextResource;
       
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
   
    /**
     * Gets text color
     * @return the text color
     */
    public int getTextColor() {
        return textColor;
    }
   
    /**
     * Sets text color
     * @param textColor the text color to set
     */
    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }
   
    /**
     * Gets text size
     * @return the text size
     */
    public int getTextSize() {
        return textSize;
    }
   
    /**
     * Sets text size
     * @param textSize the text size to set
     */
    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }
   
    /**
     * Gets resource Id for items views
     * @return the item resource Id
     */
    public int getItemResource() {
        return itemResourceId;
    }
   
    /**
     * Sets resource Id for items views
     * @param itemResourceId the resource Id to set
     */
    public void setItemResource(int itemResourceId) {
        this.itemResourceId = itemResourceId;
    }
   
    /**
     * Gets resource Id for text view in item layout
     * @return the item text resource Id
     */
    public int getItemTextResource() {
        return itemTextResourceId;
    }
   
    /**
     * Sets resource Id for text view in item layout
     * @param itemTextResourceId the item text resource Id to set
     */
    public void setItemTextResource(int itemTextResourceId) {
        this.itemTextResourceId = itemTextResourceId;
    }

    /**
     * Gets resource Id for empty items views
     * @return the empty item resource Id
     */
    public int getEmptyItemResource() {
        return emptyItemResourceId;
    }

    /**
     * Sets resource Id for empty items views
     * @param emptyItemResourceId the empty item resource Id to set
     */
    public void setEmptyItemResource(int emptyItemResourceId) {
        this.emptyItemResourceId = emptyItemResourceId;
    }
   
   
    /**
     * Returns text for specified item
     * @param index the item index
     * @return the text of specified items
     */
    protected abstract CharSequence getItemText(int index);

    @Override
    public View getItem(int index, View convertView, ViewGroup parent) {
        if (index >= 0 && index < getItemsCount()) {
            if (convertView == null) {
                convertView = getView(itemResourceId, parent);
            }
            TextView textView = getTextView(convertView, itemTextResourceId);
            if (textView != null) {
                CharSequence text = getItemText(index);
                if (text == null) {
                    text = "";
                }
                textView.setText(text);
   
                if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) {
                    configureTextView(textView);
                }
            }
            return convertView;
        }
        return null;
    }

    @Override
    public View getEmptyItem(View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = getView(emptyItemResourceId, parent);
        }
        if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) {
            configureTextView((TextView)convertView);
        }
           
        return convertView;
        }

    /**
     * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views.
     * @param view the text view to be configured
     */
    protected void configureTextView(TextView view) {
        view.setTextColor(textColor);
        view.setGravity(Gravity.CENTER);
        view.setTextSize(textSize);
        view.setLines(1);
        view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
    }
   
    /**
     * Loads a text view from view
     * @param view the text view or layout containing it
     * @param textResource the text resource Id in layout
     * @return the loaded text view
     */
    private TextView getTextView(View view, int textResource) {
        TextView text = null;
        try {
            if (textResource == NO_RESOURCE && view instanceof TextView) {
                text = (TextView) view;
            } else if (textResource != NO_RESOURCE) {
                text = (TextView) view.findViewById(textResource);
            }
        } catch (ClassCastException e) {
            Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "AbstractWheelAdapter requires the resource ID to be a TextView", e);
        }
       
        return text;
    }
   
    /**
     * Loads view from resources
     * @param resource the resource Id
     * @return the loaded view or null if resource is not set
     */
    private View getView(int resource, ViewGroup parent) {
        switch (resource) {
        case NO_RESOURCE:
            return null;
        case TEXT_VIEW_ITEM_RESOURCE:
            return new TextView(context);
        default:
            return inflater.inflate(resource, parent, false);  
        }
    }
}



AbstractWheelAdapter.java:
--------------------------

/*
 *  Copyright 2011 Yuri Kanivets
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package kankan.wheel;

import java.util.LinkedList;
import java.util.List;

import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;

/**
 * Abstract Wheel adapter.
 */
public abstract class AbstractWheelAdapter implements WheelViewAdapter {
    // Observers
    private List<DataSetObserver> datasetObservers;
   
    @Override
    public View getEmptyItem(View convertView, ViewGroup parent) {
        return null;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        if (datasetObservers == null) {
            datasetObservers = new LinkedList<DataSetObserver>();
        }
        datasetObservers.add(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        if (datasetObservers != null) {
            datasetObservers.remove(observer);
        }
    }
   
    /**
     * Notifies observers about data changing
     */
    protected void notifyDataChangedEvent() {
        if (datasetObservers != null) {
            for (DataSetObserver observer : datasetObservers) {
                observer.onChanged();
            }
        }
    }
   
    /**
     * Notifies observers about invalidating data
     */
    protected void notifyDataInvalidatedEvent() {
        if (datasetObservers != null) {
            for (DataSetObserver observer : datasetObservers) {
                observer.onInvalidated();
            }
        }
    }
}

11 comments:

Anonymous said...

Fantastic web site. Lots of useful information here.
I am sending it to some friends ans also sharing in delicious.
And obviously, thank you on your sweat!

My web blog :: family plan

Anonymous said...

What's up to all, how is the whole thing, I think every one is getting more from this website, and your views are good designed for new viewers.

my web page The Unexplained Arena Of cash advances

Anonymous said...

I couldn't resist commenting. Well written!

My homepage - information

Anonymous said...

May I simply say what a relief to uncover somebody who genuinely
knows what they're talking about over the internet. You actually know how to bring a problem to light and make it important. A lot more people have to look at this and understand this side of the story. I was surprised that you're not more popular since you most certainly possess the gift.


my site :: information

Anonymous said...

I'll right away snatch your rss as I can not in finding your email subscription link or newsletter service. Do you've any?
Please let me understand in order that I may subscribe. Thanks.


Also visit my homepage :: about

Unknown said...

Thanks friends for sharing your comments.

Anonymous said...

Wow, that's what I was exploring for, what a material! present here at this web site, thanks admin of this website.

my web page ... Www.Accounting-Services.Co.Za

Anonymous said...

I'm really enjoying the design and layout of your blog. It's a very easy on the eyes which makes
it much more enjoyable for me to come here and visit more often.
Did you hire out a developer to create your theme? Great work!


Also visit my weblog http://www.netlinkcomputers.co.za

Anonymous said...

I almost never comment, but i did a few searching and wound up here "Timer Whell like Iphone".
And I do have some questions for you if it's allright. Is it only me or does it look like a few of the responses look like they are left by brain dead individuals? :-P And, if you are writing on additional online social sites, I would like to keep up with anything new you have to post. Could you make a list of all of your social sites like your twitter feed, Facebook page or linkedin profile?

Here is my homepage: information

Anonymous said...

obviously like your web site however you have to test the spelling on
several of your posts. Many of them are rife with spelling problems and I to find
it very troublesome to inform the reality however I will certainly come
again again.

Have a look at my web site Seo Services Company at www.ozelsolutions.com

Anonymous said...

Hello my family member! I want to say that this post is awesome, great written and come with
approximately all vital infos. I would like to peer extra posts like this .



Also visit my site :: Tracie ()