Android Development Time Dial

Source: Internet
Author: User
<span id="Label3"></p><p><p>first, A recent project has encountered the need for time scale, in the internet did not find the right, so they took some time to achieve, now share, the effect such as:</p></p><p><p></p></p><p><p>Before describing how to implement this, we will introduce a function of this time scale:</p></p><p><p>1, display the current time, and can drag the first day or the next day,</p></p><p><p>2. Draw the blue part according to the time block passed in</p></p><p><p>second, The Code implementation</p></p><pre name="code" class="java">public class Scalepanel extends View {public interface onvaluechangelistener {public void Onvaluechange (float value);/** * Value no longer changes, end point * * @param mcalendar * dial current time */public void Onvaluechangeend (Calendar mcalendar);} public static final int mod_type_half = 2;public static final int mod_type_one = 10;private static final int item_half_div IDER = 60;private static final int item_max_height = 10;private static final int text_size = 14;private float mdensity;/** * Current tick value */private int mvalue = 12;private int mlinedivider = item_half_divider;private float mlastx;/** * Record the offset of the slide of the dial */p rivate float mmove;private float mwidth, mheight;private int mminvelocity;private Scroller mscroller;private Velocitytracker mvelocitytracker;private Onvaluechangelistener mlistener;/** * Width of date text */float textWidth = 0;private Textpaint textpaint, dateandtimepaint;private Paint linepaint;private boolean isneeddrawableleft, isNeedDrawableRight ;p rivate Calendar mcalendar;private Paint middlepaint, Bgcolorpaint;/** * */private Boolean ischangefrominside;public Boolean isend;//to draw the background color, draw from left to right, record the left and right point of time in the screen private Calendar leftcalendar, rightcalendar;private list<tvideofile> data;private int hour, minute, second;int gap = a, in Dexwidth = 4, indextitlewidth =, indextitlehight = 10,shadow = 6; String color = "#FA690C"; String datestr, timestr;public scalepanel (context context, attributeset attrs) {super (context, attrs); mscroller = new SCR Oller (getcontext ()); mdensity = getcontext (). getresources (). getdisplaymetrics (). density;mminvelocity = Viewconfiguration.get (getcontext ()). getscaledminimumflingvelocity (); linepaint = new Paint (); Linepaint.setstrokewidth (2); linepaint.setcolor (color.parsecolor ("#464646")); bgcolorpaint = new Paint (); Bgcolorpaint.setstrokewidth (2); bgcolorpaint.setcolor (color.parsecolor ("#00a3dd")); textpaint = new Textpaint ( paint.anti_alias_flag); textpaint.settextsize (text_size * mdensity);d ateandtimepaint = new Textpaint (Paint.ANTI_ Alias_flag);d Ateandtimepaint.settextSize (mdensity); middlepaint = new Paint (); scaleunit = mlinedivider * Mdensity;mcalendar = calendar.getinstance (); init DateAndTime (mcalendar); Leftcalendar = calendar.getinstance (); Rightcalendar = calendar.getinstance ();} /** * Calculates deviations based on time, (minute*60+second) *scaleunit/3600 */private void initoffset () {mmove = (minute * + second) * scaleunit /3600;} private void Initdateandtime (Calendar mcalendar) {this.mcalendar = Mcalendar;hour = Mcalendar.get (calendar.hour_of_day ); minute = mcalendar.get (calendar.minute); second = mcalendar.get (calendar.second); mvalue = Hour;initoffset ();} /** * Set the current time of the dial by setting the calendar * * @param mcalendar */public void Setcalendar (Calendar mcalendar) {//user finger when dragging the dial, do not receive external New to avoid conflicts if (!ischangefrominside) {initdateandtime (mcalendar); initoffset (); invalidate ();}} /** * Sets the listener for receiving results * * @param listener */public void Setvaluechangelistener (onvaluechangelistener listener) {mlistener = listener;} /** * Gets the current tick value * * @return */public float getValue () {return mvalue;} @Overrideprotected void onlayout (boolean changed, int left, int top, int right,int bottom) {mwidth = getwidth (); mheight = getheight ( ); super.onlayout (changed, left, top, right, bottom);} @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);d rawmiddleline (canvas);d rawscaleline (canvas);} Private float Offsetpercent;private float scaleunit;private Boolean ischange = false;/** * Line bottom position */float linebottom;/** * Get position at top of line */float linetop;/** * Draw tick marks from center to side * * @param canvas */private void drawscaleline (canvas Canvas) {canvas.save ( ); Isneeddrawableleft = True;isneeddrawableright = true;float width = Mwidth;float xposition = 0;linebottom = Mheight-get Paddingbottom (); linetop = linebottom-mdensity * Item_max_height;if (data! = null && data.size () > 0) {calulat Edrawposition (canvas);} The value of Mvalue is controlled between 0~23 if (mvalue > 0) {mvalue = mvalue%;} else if (mvalue < 0) {mvalue = mvalue% 24 + 24;} If (mmove < 0) {//swipe left if (mvalue = = 0 && hour! =) {mcalendar.set (calendaR.day_of_month,mcalendar.get (calendar.day_of_month)-1);} hour = Mvalue-1;//slide to the previous day 23 o'clock if (hour = =-1) {hour = 23;} Offsetpercent = 1 + mmove/scaleunit;} else if (mmove >= 0) {//swipe right, offsetpercent = Mmove/scaleunit;hour = mvalue;//slide to 0 o'clock next day, if (hour = = 0 &&!ischang E) {//if There is no ischange, the day will be repeated with a mcalendar.set (calendar.day_of_month,mcalendar.get (calendar.day_of_month) when hour==0 + 1);//avoid Repeating day+1ischange = true;}} If (hour! = 0) {//when hour switches to a different value, set the flag to the default value Ischange = false;} Countminandsecond (offsetpercent);d rawtimetext (canvas), for (int i = 0; true; i++) {//start drawing to the right xposition = (width/2-mmove) + i * scaleunit;if (isneeddrawableright && xposition + getpaddingright () < Mwidth) {//inner scale in view range Canvas.drawl Ine (xposition, linetop, xposition, linebottom,linepaint); textWidth = layout.getdesiredwidth (int2str (mvalue + i), textpaint); canvas.drawtext (int2str (mvalue + i), xposition-(textwidth/2), lineTop-5, textpaint);} else {isneeddrawableright = false;} Start on the left to draw if (i > 0){//prevent Middle Tick draw two times xposition = (width/2-mmove)-i * scaleunit;if (isneeddrawableleft && xposition > Getpaddingl EFT ()) {canvas.drawline (xposition, linetop, xposition, linebottom,linepaint); textWidth = Layout.getdesiredwidth ( Int2str (mvalue-i), textpaint) canvas.drawtext (int2str (mvalue-i), xposition-(textwidth/2), lineTop-5, textPaint);} else {isneeddrawableleft = false;}} Exit the loop when you don't need to draw left or right, end the draw operation if (!isneeddrawableleft &&!isneeddrawableright) {break;}} Canvas.restore ();} /** * There is still a problem, if the data volume is too large, that is, the user search time span is too large, this way must not be stuck. * So later you have to get the current playback location, and then select a day or so of time, so that the amount of data will not be too large * now in line with the principle of optimization first, record this problem, and then do the modification optimization * * @param canvas */private void calulate Drawposition (canvas Canvas) {//distance and time correspond ((mwidth/2/scaleunit) *3600*1000) long timeoffset = (long) ((mwidth/2/scaleuni T) * 3600 *), long middletime = Mcalendar.gettimeinmillis ();//time offset to calculate the left and right times Leftcalendar.settimeinmillis ( middletime-timeoffset); Rightcalendar.settimeinmillis (middletime + timeoffset);//find time to startAfter the order to the right, until the drawing to the right of the screen, the key is to find the time start Point//time start point is where to start drawing background color for (int position = 0; Position < Data.size (); Position++) { Tvideofile tvideofile = Data.get (position); Calendar Startcalendar = tvideofile.starttime; Calendar Endcalendar = tvideofile.endtime;if (leftcalendar.before (startcalendar) && rightcalendar.after ( Startcalendar) {//from start Draw drawbgcolor (canvas, startcalendar, endcalendar, position); break;} else if ( Leftcalendar.after (startcalendar) && Leftcalendar.before (endcalendar)) {//from left to start drawing Drawbgcolor (canvas, leftcalendar, endcalendar, position); /** * * @param canvas * @param start * The position where the first background color begins * @param distance * The length of the first background color * @param position * The first background color is in the position of the time fragment in data, and the next block begins with the position+1 */public void Drawbgcolor (canvas canvas, Calendar starttime,ca Lendar endTime, int Position) {//based on time to obtain the specific position on the dial float startposition = getpositionbytime (startTime); float endposition = Getpositionbytime (endTime);d Rawbgcolorrect (startposition, LineTop, endposition, linebottom, canvas); for (int i = position + 1; i < data.size (); i++) {tvideofile tvideofile = data.ge T (i); Calendar Startcalendar = tvideofile.starttime; Calendar Endcalendar = tvideofile.endtime;startposition = getpositionbytime (startcalendar); endposition = Getpositionbytime (endcalendar), if (startposition <= mwidth) {//draw only drawbgcolorrect within the screen area (startposition, LineTop , endposition,linebottom, canvas);} else {break;}}} /** * Painting Background color * * @param canvas */private void drawbgcolorrect (float left, float top, float right,float bottom, Canvas Canva S) {canvas.drawrect (left, top, right, bottom, bgcolorpaint);} /** * Get a specific position on the dial based on time * * @param calendar * @return */public float getpositionbytime (calendar calendar) {long middletime = Mcalendar.gettimeinmillis (); Float position = 0;long Timeoffset = Middletime-calendar.gettimeinmillis (); if (TIMEOFFSE T >= 0) {position = (float) (mwidth/2-(1.0 * timeoffset/3600/1000) * scaleunit);} Else {position = (float) (mwid Th/2-(1.0 * TIMEOFFSET/3600/1000) * scaleunit);} Return position;} /** * ready to draw background color data */public void Settimedata (list<tvideofile> data) {this.data = data;} /** * Draw Date Time text * * @param canvas */private void drawtimetext (canvas canvas) {mcalendar.set (calendar.hour_of_day, HOUR); MC Alendar.set (calendar.minute, MINUTE); mcalendar.set (calendar.second, SECOND); timestr = Date2timestr ( Mcalendar.gettime ()); textWidth = layout.getdesiredwidth (timestr, textpaint); canvas.drawtext (timestr, MWIDTH/2 + 15 * mdensity, 50,dateandtimepaint);d Rawdatetext (canvas);} private void Drawdatetext (canvas canvas) {datestr = date2datestr (mcalendar.gettime ()); textWidth = Layout.getdesiredwidth (datestr, textpaint); canvas.drawtext (datestr, mwidth/2-textWidth-35 * mdensity, 50,dateAndTim epaint);} /** * Calculate minutes and seconds * @param percent * @return */public int[] countminandsecond (float percent) {minute = (int) (3600 * percent/ Second = (int) (3600 * percent); return new int[] {minute, second};} /** * Draw the middle of the red indicator lines, shadows and so On. Indicator lineThe ends simply use two rectangles instead of * * @param canvas */private void drawmiddleline (canvas canvas) {canvas.save (); middlepaint.setstrokewidth ( indexwidth); middlepaint.setcolor (color.parsecolor (Color)); canvas.drawline (mwidth/2, 0, mwidth/2, mHeight, middlepaint); Canvas.restore ();} @Overridepublic boolean ontouchevent (motionevent event) {int action = event.getaction (); int xposition = (int) Event.getx ( ); if (mvelocitytracker = = Null) {mvelocitytracker = Velocitytracker.obtain ();} Mvelocitytracker.addmovement (event); Switch (action) {case MotionEvent.ACTION_DOWN:mScroller.forceFinished (true); MLASTX = Xposition;ischangefrominside = true;break;case MotionEvent.ACTION_MOVE:mMove + = (mlastx-xposition); Changemoveandvalue (); break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:countMoveEnd (); Countvelocitytracker (event); return false;default:break;} MLASTX = Xposition;return true;} private void Changemoveandvalue () {float fvalue = mmove/scaleunit;int TValue = (int) Fvalue;//after sliding more than one cell, record the value on the current dial if (Ma Th.abs (fValue) > 0) {mvalue + = Tvalue;//offset is always less than one grid mmove-= TValue * Scaleunit;notifyvaluechange ();p ostinvalidate ();}} private void Countvelocitytracker (motionevent event) {mvelocitytracker.computecurrentvelocity (+); float xvelocity = mvelocitytracker.getxvelocity (), if (math.abs (xvelocity) > Mminvelocity) {mscroller.fling (0, 0, (int) xvelocity, 0, integer.min_value,integer.max_value, 0, 0);} else {notifychangeover ();}} private void countmoveend () {mlastx = 0;notifyvaluechange ();p ostinvalidate ();} private void Notifyvaluechange () {if (null! = mlistener) {mlistener.onvaluechange (mvalue);}} private void Notifychangeover () {if (null! = mlistener) {mlistener.onvaluechangeend (mcalendar);} Ischangefrominside = false;} @Overridepublic void Computescroll () {super.computescroll (); if (mscroller.computescrolloffset ()) {if ( Mscroller.getcurrx () = = Mscroller.getfinalx ()) {//overcountmoveend (); notifychangeover ();} else {int xposition = Mscroller.getcurrx (); Mmove + = (mlastx-xposition); ChangemoveandValue (); mlastx = xposition;}}} Public String int2str (int i) {if (i > 0) {i = i%;} else if (i < 0) {i = i% 24 + 24;} String str = string.valueof (i), if (str.length () = = 1) {return "0" + str + ": xx";} else if (str.length () = = 2) {return str + ": 00";} Return "";} Public String date2datestr (date Date) {simpledateformat dateformat = new SimpleDateFormat ("yyyy-mm-dd"); return Dateformat.format (date);} Public String date2timestr (date Date) {simpledateformat dateformat = new SimpleDateFormat ("HH:mm:ss"); return Dateformat.format (date);}}</pre>I provided the Setcalendar method for the outside world to set the current time of the dial, and provided Onvaluechange (float Value) and Onvaluechangeend (Calendar Mcalendar) To provide real-time monitoring and sliding end monitoring, If you want to draw the background color of the time block<pre name="code" class="java">public class Mainactivity extends Activity implements Onvaluechangelistener {/** * Time scale disk */private Scalepanel scalepanel;l ist<tvideofile> data = new arraylist<tvideofile> (), @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); setcontentview (r.layout.activity_main); initData (); Scalepanel = (scalepanel) Findviewbyid (r.id.scalepanel); scalepanel.setvaluechangelistener (this); Calendar Mcalendar = calendar.getinstance ();//set time block data scalepanel.settimedata,//set current time Scalepanel.setcalendar ( mcalendar);} private void InitData () {for (int houroffset =-5; Math.Abs (houroffset) <= 5; Houroffset++) {addtimebloack (houroffset);}} private void Addtimebloack (int houroffset) {tvideofile file = new Tvideofile (); Calendar startTime = calendar.getinstance (); starttime.set (calendar.hour_of_day, starttime.get (calendar.hour_of_day ) + houroffset); Starttime.set (calendar.minute, 0); file.starttime = startTime; Calendar endTime = calendar.getinstance (); endtime.set (calendar.hour_of_day, endtime.get (calendar.hour_of_day) + houroffset); endtime.set (calendar.minute, 50); File.endtime = Endtime;data.add (file);} @Overridepublic void Onvaluechange (float value) {} @Overridepublic void onvaluechangeend (Calendar Mcalendar) {}}</pre><p><p>Specific implementation can look at the code and comments, Some of the code about the use of scroller I did not do any explanation, if you are not very familiar with the use of scroller, you can read the article on the Android development of the scroller use of the detailed</p></p><p><p>If you don't understand, you can discuss it with Me.</p></p><p><p>Finally leave a demo, if you need to see, Welcome to leave your valuable comments.<br></p></p><br><p><p>Android Development Time Dial</p></p></span>

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.