Implementation of Android iPhone wheel control and source code analysis (1)

Source: Internet
Author: User

We recommend that you download the code at the bottom of this Article for more code!


First, let's take a look:


The three figures are simple examples of using the scroll control to implement the city, random number and time. Of course, the interface is a bit simple. Next we will take the time as an example to start parsing.

First, let's take a look at the layout file:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_height="wrap_content"android:layout_width="fill_parent"android:layout_marginTop="12dp"android:orientation="vertical"android:background="@drawable/layout_bg"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_height="wrap_content"android:layout_width="fill_parent"android:layout_gravity="center_horizontal"android:paddingLeft="12dp"android:paddingRight="12dp"android:paddingTop="10dp">    <kankan.wheel.widget.WheelView android:id="@+id/hour"android:layout_height="wrap_content"android:layout_width="fill_parent"android:layout_weight="1"/><kankan.wheel.widget.WheelView android:id="@+id/mins"android:layout_height="wrap_content"android:layout_width="fill_parent"android:layout_weight="1"/></LinearLayout><TimePicker android:id="@+id/time"android:layout_marginTop="12dp"android:layout_height="wrap_content"android:layout_width="fill_parent"android:layout_weight="1"/></LinearLayout>

There are only three controls, two custom wheelviews, and a timepicker. Then, go to the code and take a look:

public class TimeActivity extends Activity {// Time changed flagprivate boolean timeChanged = false;//private boolean timeScrolled = false;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.time_layout);final WheelView hours = (WheelView) findViewById(R.id.hour);hours.setAdapter(new NumericWheelAdapter(0, 23));hours.setLabel("hours");final WheelView mins = (WheelView) findViewById(R.id.mins);mins.setAdapter(new NumericWheelAdapter(0, 59, "%02d"));mins.setLabel("mins");mins.setCyclic(true);final TimePicker picker = (TimePicker) findViewById(R.id.time);picker.setIs24HourView(true);// set current timeCalendar c = Calendar.getInstance();int curHours = c.get(Calendar.HOUR_OF_DAY);int curMinutes = c.get(Calendar.MINUTE);hours.setCurrentItem(curHours);mins.setCurrentItem(curMinutes);picker.setCurrentHour(curHours);picker.setCurrentMinute(curMinutes);// add listenersaddChangingListener(mins, "min");addChangingListener(hours, "hour");OnWheelChangedListener wheelListener = new OnWheelChangedListener() {public void onChanged(WheelView wheel, int oldValue, int newValue) {if (!timeScrolled) {timeChanged = true;picker.setCurrentHour(hours.getCurrentItem());picker.setCurrentMinute(mins.getCurrentItem());timeChanged = false;}}};hours.addChangingListener(wheelListener);mins.addChangingListener(wheelListener);OnWheelScrollListener scrollListener = new OnWheelScrollListener() {public void onScrollingStarted(WheelView wheel) {timeScrolled = true;}public void onScrollingFinished(WheelView wheel) {timeScrolled = false;timeChanged = true;picker.setCurrentHour(hours.getCurrentItem());picker.setCurrentMinute(mins.getCurrentItem());timeChanged = false;}};hours.addScrollingListener(scrollListener);mins.addScrollingListener(scrollListener);picker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {public void onTimeChanged(TimePicker  view, int hourOfDay, int minute) {if (!timeChanged) {hours.setCurrentItem(hourOfDay, true);mins.setCurrentItem(minute, true);}}});}/** * Adds changing listener for wheel that updates the wheel label * @param wheel the wheel * @param label the wheel label */private void addChangingListener(final WheelView wheel, final String label) {wheel.addChangingListener(new OnWheelChangedListener() {public void onChanged(WheelView wheel, int oldValue, int newValue) {wheel.setLabel(newValue != 1 ? label + "s" : label);}});}}

Take a look, the methods used to call the wheelview include setadapter (), setlabel ("mins"), setcyclic (true), setcurrentitem (), getcurrentitem (), addchanginglistener (), addscrollinglistener () in these methods, setaapter sets the data adapter, setcyclic () sets whether it is a loop, setcurrentitem and getcurrentitem respectively set the currently selected item and return the currently selected item. In the following two methods for setting the listener, you need to rewrite the following two interfaces:

/** * 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);}

And

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

A typical callback method is used here.

Now, let's go to the wheelview class and see how it is built. First, the wheelview inherits the View class. Lines 22 to 45 of the Code are the required classes for import. Rows 54 to 135 declare some variables and classes:

/** Scrolling duration */private static final int SCROLLING_DURATION = 400;/** Minimum delta for scrolling */private static final int MIN_DELTA_FOR_SCROLLING = 1;/** Current value & label text color */private static final int VALUE_TEXT_COLOR = 0xF0000000;/** Items text color */private static final int ITEMS_TEXT_COLOR = 0xFF000000;/** Top and bottom shadows colors */private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111,0x00AAAAAA, 0x00AAAAAA };/** Additional items height (is added to standard text item height) */private static final int ADDITIONAL_ITEM_HEIGHT = 15;/** Text size */private static final int TEXT_SIZE = 24;/** Top and bottom items offset (to hide that) */private static final int ITEM_OFFSET = TEXT_SIZE / 5;/** Additional width for items layout */private static final int ADDITIONAL_ITEMS_SPACE = 10;/** Label offset */private static final int LABEL_OFFSET = 8;/** 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 Valuesprivate WheelAdapter adapter = null;private int currentItem = 0;// Widthsprivate int itemsWidth = 0;private int labelWidth = 0;// Count of visible itemsprivate int visibleItems = DEF_VISIBLE_ITEMS;// Item heightprivate int itemHeight = 0;// Text paintsprivate TextPaint itemsPaint;private TextPaint valuePaint;// Layoutsprivate StaticLayout itemsLayout;private StaticLayout labelLayout;private StaticLayout valueLayout;// Label & backgroundprivate String label;private Drawable centerDrawable;// Shadows drawablesprivate GradientDrawable topShadow;private GradientDrawable bottomShadow;// Scrollingprivate boolean isScrollingPerformed; private int scrollingOffset;// Scrolling animationprivate GestureDetector gestureDetector;private Scroller scroller;private int lastScrollY;// Cyclicboolean isCyclic = false;// Listenersprivate List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();

Here, staticlayout is used and you can find this class in the development document:

StaticLayout is a Layout for text that will not be edited after it is laid out. Use DynamicLayout for text that may change.This is used by widgets to control text layout. You should not need to use this class directly unless you are implementing your own widget or custom display object, or would be tempted to call Canvas.drawText() directly.

Staticlayout cannot be modified after being created. It is usually used to control the layout of text components.

The drawable, text 'paint, gradientdrawable, gesturedetector, and scroller classes are also used. In the development documents, the gradientdrawable overview is as follows:

A Drawable with a color gradient for buttons, backgrounds, etc.It can be defined in an XML file with the <shape> element. For more information, see the guide to Drawable Resources.

That is to say, this class can provide gradient color rendering for buttons or backgrounds.

Textpaint Overview:

TextPaint is an extension of Paint that leaves room for some extra data used during text measuring and drawing.

Textpaint is an extension of the paint class. It is mainly used to set aside space for the attachment data during text painting.


Gesturedetector: gesture detection. For more information about this class, see the development documentation:

Detects various gestures and events using the supplied MotionEvents. The GestureDetector.OnGestureListener callback will notify users when a particular motion event has occurred. This class should only be used with MotionEvents reported via touch (don't use for trackball events).

Provides motionevents for various gestures and events. When a specific event occurs, the callback function gesturedetector. ongesturelistener is called. This class should only apply to events triggered by motionevents through touch (do not use tracking events ).


Rows 140 to 156 are constructor methods, and rows 175 to 183 are set and getadapter. In row 3, set the animation interface interpolator by using the setinterpolator () method. Let's take a look at the overview of this interface:

An interpolator defines the rate of change of an animation. This allows the basic animation effects (alpha, scale, translate, rotate) to be accelerated, decelerated, repeated, etc.

Defines an animation based on variability. This allows the basic animation effects (alpha, scale, translate, and rotate) to accelerate, slow down, and repeat. This method is used in the random number example.

Set the number of items displayed from rows 1 to 203. In the setvisibleitems () method, the invalidate () method of view is called. See the Introduction to this method in the following document:

Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().

Invalidate all views. If the view is visible, the ondraw () method is called from the UI thread.

Lines 223 to 233 set label, which is the hours in the image below.

Rows 245 to 296 are listener settings. I have simply mentioned the above. I will not describe it here.

Rows 307 to 349 are set to the selected item, which is the part in the shadow box, which is relatively simple. Scroll is mainly called in this method:

/** * Scroll the wheel * @param itemsToSkip items to scroll * @param time scrolling duration */public void scroll(int itemsToScroll, int time) {scroller.forceFinished(true);lastScrollY = scrollingOffset;int offset = itemsToScroll * getItemHeight();scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time);setNextMessage(MESSAGE_SCROLL);startScrolling();}

Rows 357 to 365 are used to set whether the item data can be recycled.

The initresourcesifnecessary () method of line 1, literally, if the resource needs to be initialized.

private void initResourcesIfNecessary() {if (itemsPaint == null) {itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG| Paint.FAKE_BOLD_TEXT_FLAG);//itemsPaint.density = getResources().getDisplayMetrics().density;itemsPaint.setTextSize(TEXT_SIZE);}if (valuePaint == null) {valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG| Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG);//valuePaint.density = getResources().getDisplayMetrics().density;valuePaint.setTextSize(TEXT_SIZE);valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0);}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);}

This method is initialized to call this method in the calculatelayoutwidth () method of row 532, And the getmaxtextlength () method of row 487 is also called.

Row 471 gettextitem (INT index) obtains the text of the item through an index.


This is the first part. There are not many interesting points. The key points are the content from the next 532 rows to the next 940 rows. Let's start with another article and start the analysis first.

Finally:

Android-Like iPhone-like scroll control source code

Http://download.csdn.net/detail/aomandeshangxiao/4175719

Not complete to be continued! Next article: Implementation of the android iPhone-like scroll wheel control and source code analysis (2)



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.