Wheel Series Wheel Selector tool--wheelview

Source: Internet
Author: User
Tags gety

Realize the selection function of the runner, see the effect:

This project is modified by this project, but basically in addition to the original general framework, the internal implementation of the logic has made a lot of changes, you crossing can compare the reference, here must thank the original author to enlighten me.

First on the source: Wheelview

The basic steps to implement a custom view are:
* Design Attribute Properties
* Implement the constructor, read the attribute property in the constructor, and use the
* Overriding the Onmeasure method
* Overriding the OnDraw method

These basic parts are not elaborate, if this part of the understanding, you can look at my previous article, you can also directly from the source to find the answer. This article focuses on how the scrolling animation in this view is designed, implemented, and tuned, as well as some thoughts that are difficult to express in the source code, but the combination of source can better understand this article.

Idea

Referring to the previous, let's think about, we should be able to customize which properties of this view:

attr property
linecolor split line Color
lineheight split line height
itemnumber This wheelview shows the number of items
noempty set True to select cannot be empty, otherwise it can be empty
normaltextcolor
normaltextsize
selectedtextcolor select text color
selectedtextsize select text font size
unitheight height of each item unit

What is the function of such a view and how does it respond?
* First, at least to be able to roll up, especially when the finger fast-moving, can continue to scroll a distance, this distance should be related to the strength of the finger sliding
* Scrolling speed should be fast after slow, deceleration stop
* When scrolling, be able to determine which item should be selected, i.e. where it should be parked.
* If sliding again in the process of sliding, should slide farther
* When you click on the top and bottom of the runner, you should create a single-step selection effect.
* The rollers should be restored to their original state after being slightly disturbed.

How to get the screen moving.

This problem has experienced children's shoes have been done, simply say:
1. According to the existing state a0 and the input information (obtained from the ontouchevent), the end of the animation to calculate the state of an;
2. Between the end state and the current state, am=f (am-1), or am=g (am), is used to calculate the finite point a1, a 2 that is about to be inserted ..... An-1, first set i=1;
3. Calculation of aI;
4. Call the Invalidate () function to redraw the screen;
5. Wait for a period of time t to make i=i+1;
6. Repeat 3, 4, 5 until i=n.

Design function functions

Now we know that in order for the screen to move, we should handle the touch event in the Ontouchevent function.

@Override Public Boolean ontouchevent(Motionevent event) {if(!isenable)return true;inty = (int) event.gety ();intmove = Math.Abs (Y-downy);Switch(Event.getaction ()) { CaseMotionevent.action_down://Prevent other sliding view preemption focus, such as nesting in the ListView when usedGetParent (). Requestdisallowintercepttouchevent (true);if(isscrolling) {isgoonmove=false;if(Movehandler! =NULL) {//Clear the current quick slide animation and go to the next slide actionMovehandler.removemessages (Go_on_move_refresh);                Movehandler.sendemptymessage (go_on_move_interrupted); }} isscrolling =true; DownY = (int) event.gety (); Downtime = System.currenttimemillis (); Break; CaseMotionevent.action_move:isgoonmove=false; Isscrolling =true;            Actionmove (Y-downy); Onselectlistener (); Break; CaseMOTIONEVENT.ACTION_UP:LongTime= System.currenttimemillis ()-downtime;//Determine the distance traveled during this time            if(Time < Goontime && move > Goonmindistance)            {Goonmove (time,y-downy); }Else{//If the moving distance is small, it is considered a click event, otherwise it is considered a small distance sliding                if(move<clickdistance) {if(Downy<unitheight* (itemnumber/2) &&downY>0){//If you do not move again up, but directly up, you cannot create a sliding effect when clicked                        //Adjust the effect of clicks by adjusting the distance between move and upActionmove ((int) (unitheight/2)); Slowmove ((int) unitheight/4); }Else if(Downy>controlheight-unitheight* (itemnumber/2) {Actionmove (&&downy<controlheight) {-(int) (unitheight/2)); Slowmove (-(int) unitheight/4); }                }Else{Slowmove (y-downy); } isscrolling =false; } Break;default: Break; }return true;}/** * Handling Movement in Motionevent.action_move * @param Move Distance */Private void Actionmove(intMove)/** * Continue to quickly move a distance, a continuous scrolling animation, the scrolling speed decreases, the speed is reduced to slow_move_speed after the call slowmove* @param time sliding interval * @param MOVE sliding distance * *void Goonmove(LongTimeFinal LongMove)/*** move slowly for a distance, moving at a speed of slow_move_speed,* note that this distance is not a move parameter, but rather the distance from the move is shifted by the option coordinates, then the item that should be selected is then determined and then moved to the middle * Call noempty* @param move immediately set the new coordinate to move the distance, not the slow moving distance */Private void Slowmove(Final intMove)/** * cannot be empty, must have an option, the slide animation at the end of the call * to determine the current should be selected item, if it is not in the middle of the screen, then move it to the middle of the screen * @param movesymbol moving distance, actually only need its symbol, used to determine the current slide direction */Private void Noempty(intMovesymbol)

In order to prevent this article drown in the code, Actionmove, Goonmove, Slowmove, Noempty function only introduced the function, the concrete realization may shift the source view.

It should be noted that in order to ensure the smoothness of the picture, the calculation should be placed in other threads to execute, after the calculation of the drawing, the common method is to send a message to handler after the completion of the calculation, and then call Invalidate () in the handler, Alternatively, you can call the Postinvalidate () method directly to redraw it. Some of the calculations in this project are in the Goonmove, Slowmove, and noempty three functions, all of which are executed in the sub-thread (movehandler) and refresh the interface in Postinvalidate () mode.

How to produce a deceleration stop effect

When it comes to slowing down when drawing animations, many people immediately think of the Interpolator Interpolator that Android offers to us. It has an implementation class is Decelerateinterpolator, from the name can be seen as a deceleration interpolator.

When combined to this project, there is a small trick, is the use of decelerateinterpolator in the Goonmove, to perform the deceleration interpolation, when the speed slowed to a certain extent (slow_move_speed=3px), Instead, call Slowmove to do the leveling. Combined with the slowmove of the note can be seen, if the distance in the calculation of sliding, according to the number of unitheight to slide, the slow sliding distance of 0, no effect, so to a certain distance, slowmove sliding animation distance will be longer, Can get a smoother slow stop effect.

How to determine which alternative should be selected

The most important function of this project is to determine whether it can be selected and whether it has been selected. Look at the code first:

 /** * Determines whether an alternative is to be judged in the selectable area, which is used when the item is not exactly selected * Taking into account that the baseline of the text is its bottom, and that the height of the y+m is the height of the top of the text * Therefore the criterion for judging the optional area is the portion of the text that needs to be subtracted * i.e. y+ M in the middle of the center and in the middle of the upper section of the range, it is judged optional */ Public  synchronized Boolean couldselected() {Booleanisselect=true;if(y+move<=itemnumber/2*unitheight-unitheight| | y+move>=itemnumber/2*unitheight+unitheight) {isselect=false; }returnIsselect;}/** * Determine if it is just in the middle of the selection area, that is, the selected state * / Public  synchronized Boolean selected() {Booleanisselect=false;if(textrect==NULL){return false; }if((y+move>=itemnumber/2*unitheight-unitheight/2+(float) Textrect.height ()/2) && (y+move<=itemnumber/2*unitheight+unitheight/2-(float) Textrect.height ()/2)) isselect=true;returnIsselect;}

These two functions are each item that determines whether or not it is selected, where Y is the current coordinate of the item, and move is the distance that the item moves, and Y+move is the value of the top edge of the item's position in the picture. The above expression is simplified, it is difficult to see how it was pulled out, the following can help you understand better.

Shown is a 3-grid scroll wheel, which indicates several important heights, and shows how each of the options to be plotted is calculated. It is important to note that the starting point of the y+m is not the vertex in the screen, but the first vertex to be selected (that is, it may be out of the drawing area). Where th is based on the content of Normaltextsize and selectedtextsize and text calculated, specific calculation steps please see the source code.

Indicates how to calculate the results of the couldselected, it should be noted that N is an int, so the result of N/2 is actually the next rounding, so n/2*uh! =N*UH/2. If you don't understand, go to Java's operator precedence and implicit type conversions.

As you can see, the range of couldselected is exactly the range between the first option (included) and the third one to be selected (inclusive). If the scroll wheel is not more than 3, but 5, 7, then the range of the couldselected is the range of text between the upper and lower of the middle item.


indicating how to calculate the results of the selected, it can be seen that the range of selected is just the middle of the lattice, any part of the text into this lattice, this item is selected.

Now you should understand the basis of these values, but you may ask, if there are two options to be in this range, selected how to judge? Then use will make the top of the item is selected, and in fact this project in the calculation process has basically ruled out this possibility, combined with the previous introduction of the Slowmove and Noempty functions of the source code can better understand the role of couldselected and selected, As well as the entire selection and scrolling logic , concrete implementation or please move the source code.

How to handle the click action in the process of sliding

The numberpicker of the system and some other open source projects are not ideal for clicking on the swipe. A quick click in the process of sliding will result in a large chance of not centering the final results:

Actually, that's why I built my own wheels. This situation is mainly due to the following two points of design defects:
* There are problems with the way the scrolling animation itself is implemented. The benefit of creating a new thread for each quick swipe (Goonmove implementation) is that multiple threads can be used to synchronize the computations in a multi-thread, resulting in an accelerated scrolling sensation.
* Not at the end of each scroll, do a roll back to the position of the operation. In these projects, the implementation of the animation is often at the beginning of the animation to calculate the final distance to scroll, and because the scrolling animation is iterative calculation in the thread, so in the process of the calculation of a small disturbance, will lead to the entire rolling error, resulting in dislocation of the results.

So I did the corresponding treatment for these two points.

    • First, Handlerthread and handler are used to animate the animation so that only one thread is scrolled at a time, and the overhead of creating threads frequently is reduced. Then in the Ontouchevent function to interrupt the current scrolling judgment, interrupted scrolling is very simple, just set the current animation position as the starting point of the new animation. This is the same as a new scroll when the wheel is clicked again during the fast scrolling process, which is not related to the last scroll. But this requires the use of other methods to produce accelerated scrolling effect, see Goonmove function source code.

    • By using Handlerthread, the Slowmove function and the Noempty function are guaranteed to be called at the end of each scroll (and there is no synchronization problem), in which the state of the current scroll wheel is computed again, ensuring that there must be one selected when the animation stops. And the selected item is positioned in the middle of the wheel. To be blunt, it is to ensure the final effect by repeating the calculation.

How to tune Performance

To tell you the truth, I did not delve into performance tuning, so the performance of this project may not be good, but the basic logic of performance optimization, which is to reduce unnecessary computation, has two things in this project:
* When plotting each item, the th must first be calculated based on the position of Normaltextsize, selectedtextsize, text content, and item, but if Normaltextsize and selectedtextsize are equal, Each time the calculation of th is the same, so I set a Boolean to indicate whether and calculated, the calculation will not have to repeat the calculation.
* Before drawing each item, call the Isinview function to determine whether the current item is in the display area, and if not, skip the calculation and drawing of the item directly, which can greatly improve the smoothness of the animation. Note the difference between the comment line and the non-commented line in the following code.

/** * Whether in the visual interface * */ public  synchronized  Span class= "Hljs-keyword" >boolean  isinview  () {/ /if (y + move > Controlheight | | (float) y + (float) move + (float) UNITHEIGHT/2 + (float) textrect.height ()/2f) < 0)  if  (y + move > Controlheight | | ((float ) y + (float ) Move + (float ) unitheight) < 0 ) // To relax the conditions of judgment, otherwise it can not be executed at the beginning of the OnDraw, but after the calculation of th can be judged.  return  false ; return  true ;} 
Source

Wheelview
The source code will continue to update, the blog may not keep up with the progress of the source code, the source is subject to.

Tips: The core of the source code is the function of the previous introduction of the Ontouchevent,goonmove,slowmove,noempty,couldselected and selected, combined with this article, basically a look on the understanding.

Wheel Series Wheel Selector tool--wheelview

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.