From: http://ysl-paradise.blogspot.com/2009/07/android-analogclock-1.html
Android source code internals-alarm clock, analogclock (1)
The original program of zookeeper is stored here
.
One line of this program, the first sight on the page, is a big time. So today, we will start from this moment. Let's look at how it actually works.
You need to know what components are used for this time period. There are two methods. The first method is to use the hierarchy viewer in the SDK.
Tool; the other is to directly check the plane design in RES/layout. This time, we use the second method directly.
Turn alarmclock/RES/Layout
You will find a clock_xxx.xml example. Open clock_droid2.xml
. The content is as follows:
- <?
XML
Version
=
"1.0"
Encoding
=
"UTF-8"
?>
- <
Analogclock
- Xmlns: Android
=
Http://schemas.android.com/apk/res/android"
- Android: ID
=
"@ + ID/clock"
- Style
=
"@ Style/analogclock"
- Android: dial
=
"@ Drawable/clockdroid2_dial"
- Android: hand_hour
=
"@ Drawable/clockdroid2_hour"
- Android: hand_minute
=
"@ Drawable/clockdroid2_minute"
/>
<? XML version = "1.0" encoding = "UTF-8"?> <Br/> <analogclock <br/> xmlns: Android = "http://schemas.android.com/apk/res/android" <br/> Android: id = "@ + ID/clock" <br/> style = "@ style/analogclock" <br/> Android: dial = "@ drawable/clockdroid2_dial" <br/> Android: hand_hour = "@ drawable/clockdroid2_hour" <br/> Android: hand_minute = "@ drawable/clockdroid2_minute"/> <br/>
Well, it seems that android. widget. analogclock can be directly used in this phase. As long as it passes through
Android: dial, Android: hand_hour, Android: hand_minute
Attention: Specifies the timeline, the timeline and the timeline of the score. A complete timeline appears. At the top of the screen, the video is shown at this time.
No external settings are required. At this time, the component will display the time and score in the correct position according to the current time, then how does he update the time and shard location at a specific time? Note:
When the time is reached, there is only one shard for the hour and minute. From this point of view, we can guess that at this time, we will automatically rotate and adjust the time and score to the correct angle. Let's take a look at this
How does the analogclock component implement these functions.
Open analogclock component original shard
, The first limit is deducted, and the entire original limit is less than 230 rows. So few program workers can complete the functions at this time. This is also the initial component of the most popular component I have to watch.
This time, we have to look at two important points.
- In component programs, how do I know the changes in time?
- In Android, how do I rotate a video from any angle and hide it on the screen?
In component programs, how do I know the changes in time?
Originally in onattachedtowindow ()
In, analogclock passes through registerreceiver () to parse three actions issued by the system, action_time_tick
, Action_time_changed
And action_timezone_changed
.
In Android, the system sends some system notifications through the intent, and these notifications are regarded as actions. In intent
In other explanations, you can find all the definitions of actions.
There are two methods in your program to receive notifications from these systems. The first method is to define the author er in androidmanifest. xml.
This method will be mentioned in the later introduction. The second method is to use registerreceiver () to receive a type of difference to the system receiver. Caused
Analoclock exists as a component. If you still need to define this component in androidmanifest. xml every time you use this component, it will be too troublesome. Therefore,
Analoclock uses the second method.
Among them, action_time_tick is the action sent by the system every minute. Action_time_changed
Is the action sent when the user changes the system. When your phone crosses the time zone, the system will send action_timezone_changed
To a program with temporary connections.
- // #100 ~ #106
- Intentfilter filter = new
Intentfilter ();
- Filter. addaction (intent. action_time_tick );
- Filter. addaction (intent. action_time_changed );
- Filter. addaction (intent. action_timezone_changed );
- Getcontext (). registerreceiver (mintentreceiver, filter, null
, Mhandler );
// #100 ~ #106 <br/> intentfilter filter = new intentfilter (); <br/> filter. addaction (intent. action_time_tick); <br/> filter. addaction (intent. action_time_changed); <br/> filter. addaction (intent. action_timezone_changed); <br/> getcontext (). registerreceiver (mintentreceiver, filter, null, mhandler); <br/>
Once these actions are generated, they will call the broadcastreceiver that comes out at the end of the program.
Object, the onreceive () callback function in mintentreceiver.
First, in onreceive (), first check if there is a change in the time zone, then you need to reset the mcalendar variable.
- // #233 ~ #245
- Private
Final
Broadcastreceiver mintentreceiver =
- New
Broadcastreceiver (){
- @ Override
- Public
Void
Onreceive (context, intent ){
- If
(Intent. getaction (). Equals (intent. action_timezone_changed )){
- String TZ = intent. getstringextra ("time-zone"
);
- Mcalendar = new
Time (timezone. gettimezone (Tz). GETID ());
- }
- Ontimechanged ();
- Invalidate ();
- }
- };
// #233 ~ #245 <br/> private final broadcastreceiver mintentreceiver = <br/> New broadcastreceiver () {<br/> @ override <br/> Public void onreceive (context, intent) {<br/> If (intent. getaction (). equals (intent. action_timezone_changed) {<br/> string TZ = intent. getstringextra ("time-zone"); <br/> mcalendar = new time (timezone. gettimezone (Tz ). GETID (); <br/>}< br/> ontimechanged (); </P> <p> invalidate (); <br/>}< br/> }; <br/>
Ontimechanged () is used to capture the latest time and data.
- // #221 ~ #231
- Private
Void
Ontimechanged (){
- Mcalendar. settonow ();
- Int
Hour = mcalendar. hour;
- Int
Minute = mcalendar. minute;
- Int
Second = mcalendar. Second;
- MMinutes = minute + second/60
. 0f;
- Mhour = hour + mMinutes/60
. 0f;
- Mchanged = true
;
- }
// #221 ~ #231 <br/> private void ontimechanged () {<br/> mcalendar. settonow (); <br/> int hour = mcalendar. hour; <br/> int minute = mcalendar. minute; <br/> int second = mcalendar. second; <br/> mMinutes = minute + second/601_f; <br/> mhour = hour + mMinutes/601_f; <br/> mchanged = true; <br/>}< br/>
At the end of onreceive (), call view. invalidate (). This operation sends a view. ondraw () call, which is the latest time on the screen.
In Android, how do I rotate a video from any angle and hide it on the screen?
In fact, Android's 2d linear regression function is very powerful, especially the Matrix
This part. Through matrix, you can easily control the displacement, rotation, skew, amplification, and other functions of the entire base object. For example, if you want to spin up a video to 30
And then on the screen. The traditional approach is to directly scale the content of a video segment to 30 degrees by point. But in Android
On the platform, you don't need to worry about it. You only need to set the entire base system to 30 degrees, no matter whether you are upgrading or downgrading, the final result displayed on the screen is a 30-degree effect.
If you want to know how analogclock selects audio and video clips, check ondraw. I will be in ondraw (), and this part of the selection time, divided into two parts, the column is listed below. Canvas. Rotate ()
Yes. This function is used to train the platform from a different angle. After reading this example, I have not found that I want to spin up, zoom in, or zoom in on Android. In fact, I only need two or three lines of code.
- // #159 ~ #219
- @ Override
- Protected
Void
Ondraw (canvas ){
- ...
- Canvas. Save ();
- Canvas. Rotate (mhour/12
. 0f *
360
. 0f, x, y );
- Final
Drawable hourhand = mhourhand;
- If
(Changed ){
- W = hourhand. getintrinsicwidth ();
- H = hourhand. getintrinsicheight ();
- Hourhand. setbounds (X-(W/2
), Y-(H/
2
), X + (W/
2
), Y + (H/
2
));
- }
- Hourhand. Draw (canvas );
- Canvas. Restore ();
- Canvas. Save ();
- Canvas. Rotate (mMinutes/60
. 0f *
360
. 0f, x, y );
- Final
Drawable minutehand = mminutehand;
- If
(Changed ){
- W = minutehand. getintrinsicwidth ();
- H = minutehand. getintrinsicheight ();
- Minutehand. setbounds (X-(W/2
), Y-(H/
2
), X + (W/
2
), Y + (H/
2
));
- }
- Minutehand. Draw (canvas );
- Canvas. Restore ();
- ...
- }
// #159 ~ #219 <br/> @ override <br/> protected void ondraw (canvas) {<br/>... <br/> canvas. save (); <br/> canvas. rotate (mhour/12.0f * 360.0f, x, y); <br/> final drawable hourhand = mhourhand; <br/> If (changed) {<br/> W = hourhand. getintrinsicwidth (); <br/> H = hourhand. getintrinsicheight (); <br/> hourhand. setbounds (X-(W/2), Y-(H/2), X + (W/2), Y + (H/2 )); <br/>}< br/> hourhand. draw (canvas); <br/> canvas. restore (); <br/> canvas. save (); <br/> canvas. rotate (mMinutes/601_f * 360.0f, x, y); <br/> final drawable minutehand = mminutehand; <br/> If (changed) {<br/> W = minutehand. getintrinsicwidth (); <br/> H = minutehand. getintrinsicheight (); <br/> minutehand. setbounds (X-(W/2), Y-(H/2), X + (W/2), Y + (H/2 )); <br/>}< br/> minutehand. draw (canvas); <br/> canvas. restore (); <br/>... <br/>}< br/>
No constructors left in analogclock, and other functions such as onmeasure (), onsizechanged (), and ondetachedfromwindow () have not been mentioned yet. I want to leave this part for you to explore.