现在的位置: 首页 > 综合 > 正文

倒计时时钟

2012年06月21日 ⁄ 综合 ⁄ 共 17129字 ⁄ 字号 评论关闭

Clock analyze

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        
        mActionBar = getActionBar();
        mActionBar.setAlternativeTabStyle(true);
        int tabHeight = (int) getResources().getDimensionPixelSize(R.dimen.uui_tab_height);
        mActionBar.setTabHeight(tabHeight);
        mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        
        setContentView(R.layout.clock_activity_main);
        createFragmentAndTab();   --->1.1
    }

------->1.1
    private void createFragmentAndTab() {

        mFragmentsList = new ArrayList<Fragment>();
        mViewPager = (ViewPager) findViewById(R.id.tab_pager);
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment alarmFragment = new AlarmFragment();
        Fragment clockFragment = new WorldClockFragment();
        Fragment stopWatchFragment = new StopWatchFragment();
        Fragment timerFragment = new TimerFragment();  //对 TimerFragment 分析

//省略下面的分析
        mFragmentsList.add(alarmFragment);
        mFragmentsList.add(clockFragment);
        mFragmentsList.add(stopWatchFragment);
        mFragmentsList.add(timerFragment);  

        addCustomTab(TabState.TAB_ALARM_INDEX, R.drawable.ic_tab_alarm_newui,
                R.string.alarm_tab_label, new TabListener());
        addCustomTab(TabState.TAB_CLOCK_INDEX, R.drawable.ic_tab_worldclock_newui,
                R.string.worldclock_tab_label, new TabListener());
        addCustomTab(TabState.TAB_STOPWATCH_INDEX, R.drawable.ic_tab_stopwatch_newui,
                R.string.stopwatch_tab_label, new TabListener());
        addCustomTab(TabState.TAB_TIMER_INDEX, R.drawable.ic_tab_timer_newui,
                R.string.timer_tab_label, new TabListener());
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        Intent i = getIntent();
        if (i != null) {
            int tab = i.getIntExtra(CURRENT_TAB, -1);
            if (tab != -1) {
                mCurrentTab = tab;
            } else {
                mCurrentTab = mPrefs.getInt(CURRENT_TAB, TabState.TAB_ALARM_INDEX);
            }
        } else {
            mCurrentTab = mPrefs.getInt(CURRENT_TAB, TabState.TAB_ALARM_INDEX);
        }
        Log.d(TAG, "mCurrentTab = " + mCurrentTab);
        mViewPager.setOffscreenPageLimit(mTabTitle.length);
        mViewPager.setAdapter(new TabFragmentPagerAdapter(fragmentManager, mFragmentsList));
        setCurrentTab(mCurrentTab);
        mViewPager.setCurrentItem(mCurrentTab, true);

        mViewPager.setOnPageChangeListener(mPagerListener);
    }

TimerFragment.java
public class TimerFragment extends Fragment {
	
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View fragView = inflater.inflate(R.layout.fragment_timing, container, false);   --->2.1

        mStartBut = (Button) fragView.findViewById(R.id.start);
        mStopBut = (Button) fragView.findViewById(R.id.stop);
        mCancelBut = (Button) fragView.findViewById(R.id.cancel);
        mRestartBut = (Button) fragView.findViewById(R.id.restart);
        mTimePickerLayout = fragView.findViewById(R.id.fragment_timing_time_picker_layout);

        mShow = (LinearLayout) fragView.findViewById(R.id.time_picker);
        mShowTiming = (TextView) fragView.findViewById(R.id.show_timing);

        mHours = (WheelView) fragView.findViewById(R.id.hour);
        mHours.setViewAdapter(new NumericWheelAdapter(getActivity(), 0, 99));   -->important
        mHours.setCyclic(true);

        mMins = (WheelView) fragView.findViewById(R.id.mins);
        mMins.setViewAdapter(new NumericWheelAdapter(getActivity(), 0, 59, "%02d"));
        mMins.setCyclic(true);

        mSecs = (WheelView) fragView.findViewById(R.id.secs);
        mSecs.setViewAdapter(new NumericWheelAdapter(getActivity(), 0, 59, "%02d"));
        mSecs.setCyclic(true);

        mHours.setCurrentItem(0);
        mMins.setCurrentItem(1);
        mSecs.setCurrentItem(0);

        /*if ((mHours.getCurrentItem() != 0) && (mMins.getCurrentItem() != 0) && (mSecs.getCurrentItem() != 0)) {
            mStartBut.setEnabled(false);
        } else {
            mStartBut.setEnabled(true);
        }
        OnWheelChangedListener wheelListener = new OnWheelChangedListener() {
            public void onChanged(WheelView wheel, int oldValue, int newValue) {
                if (!mTimeScrolled) {
                    mSecnum = mHours.getCurrentItem() * 60 * 60 * 1000 + mMins.getCurrentItem() * 60 * 1000
                            + mSecs.getCurrentItem() * 1000;
                }
            }
        };
        mHours.addChangingListener(wheelListener);
        mMins.addChangingListener(wheelListener);
        mSecs.addChangingListener(wheelListener);

        OnWheelClickedListener click = new OnWheelClickedListener() {
            public void onItemClicked(WheelView wheel, int itemIndex) {
                wheel.setCurrentItem(itemIndex, true);
            }
        };
        mHours.addClickingListener(click);
        mMins.addClickingListener(click);
        mSecs.addClickingListener(click);

        OnWheelScrollListener scrollListener = new OnWheelScrollListener() {
            public void onScrollingStarted(WheelView wheel) {
                mTimeScrolled = true;
            }

            public void onScrollingFinished(WheelView wheel) {

                if ((mHours.getCurrentItem() * 60 * 60 == 0) && (mMins.getCurrentItem() * 60 == 0)
                        && (mSecs.getCurrentItem() == 0)) {
                    mStartBut.setEnabled(false);
                } else {
                    mStartBut.setEnabled(true);
                }

                mTimeScrolled = true;
                mSecnum = mHours.getCurrentItem() * 60 * 60 * 1000
                        + mMins.getCurrentItem() * 60 * 1000
                        + mSecs.getCurrentItem() * 1000;
            }
        };

        mHours.addScrollingListener(scrollListener);
        mMins.addScrollingListener(scrollListener);
        mSecs.addScrollingListener(scrollListener);
				*/ 注释部分省略
				
        mStartBut.setOnClickListener(new OnClickListener() {  //分析倒计时计时过程

            @Override
            public void onClick(View v) {
                mIsRunning = true;
                showPage(Utils.PAGE_COUNTDOWN_TIMER);   ---> 3.6 倒计时进入的界面
                mSecnum = mHours.getCurrentItem() * 60 * 60 * 1000 + mMins.getCurrentItem() * 60 * 1000
                        + mSecs.getCurrentItem() * 1000;
                startCountTime(mSecnum);  --->3.1 计时

            }
        });

        mStopBut.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                if (mSecnum >= 1 * 1000) {
                    mIsRunning = false;
                    mStopBut.setVisibility(View.GONE);
                    mRestartBut.setVisibility(View.VISIBLE);
                    if (mCountTimer != null) {
                        mCountTimer.cancel();
                    }
                    if (mPendingIntent != null) {
                        mAlarmManager.cancel(mPendingIntent);
                    }
                }
            }
        });

        mRestartBut.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                mIsRunning = true;
                startCountTime(mSecnum);
                mStopBut.setVisibility(View.VISIBLE);
                mRestartBut.setVisibility(View.GONE);
            }
        });

        mCancelBut.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                if (mSecnum >= 1 * 1000) {
                    if (mPendingIntent != null) {
                        mAlarmManager.cancel(mPendingIntent);
                    }
                    if (mCountTimer != null) {
                        mCountTimer.cancel();
                    }
                    mIsRunning = false;

                    mTimeScrolled = true;
                    showPage(Utils.PAGE_SETUP_TIMER);
                }
            }
        });

        return fragView;
    }

}

--->2.1
fragment_timing.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:paddingBottom="15dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="15dp" >

        <LinearLayout
            android:id="@+id/time_picker"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <LinearLayout
                android:id="@+id/fragment_timing_time_picker_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >

                <com.sprd.wheel.widget.WheelView
                    android:id="@+id/hour"
                    android:layout_width="0dp"
                    android:layout_height="212dp"
                    android:layout_weight="1" />

                <com.sprd.wheel.widget.WheelView
                    android:id="@+id/mins"
                    android:layout_width="0dp"
                    android:layout_height="212dp"
                    android:layout_weight="1" />

                <com.sprd.wheel.widget.WheelView
                    android:id="@+id/secs"
                    android:layout_width="0dp"
                    android:layout_height="212dp"
                    android:layout_weight="1" />
            </LinearLayout>
        </LinearLayout>

        <TextView
            android:id="@+id/show_timing"
            android:layout_width="match_parent"
            android:layout_height="214dp"
            android:background="@drawable/timepicker"
            android:gravity="center"
            android:textColor="@android:color/white"
            android:textSize="60sp"
            android:visibility="gone" />
    </FrameLayout>

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:background="#e4dbbd" >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/divider" />

        <Button
            android:id="@+id/start"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip"
            android:layout_marginTop="48dip"
            android:background="@drawable/start_stopwatch"
            android:enabled="false"
            android:text="@string/start_timing"
            android:textColor="#ffffffff" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/stop"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="11dip"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="35dip"
                android:layout_weight="1"
                android:background="@drawable/stop_stopwatch"
                android:text="@string/stop_timing"
                android:textColor="#ffffffff"
                android:visibility="invisible" />

            <Button
                android:id="@+id/restart"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="11dip"
                android:layout_marginLeft="10dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="35dip"
                android:layout_weight="1"
                android:background="@drawable/start_stopwatch"
                android:text="@string/restart_timing"
                android:textColor="#ffffffff"
                android:visibility="invisible" />

            <Button
                android:id="@+id/cancel"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="12dip"
                android:layout_marginLeft="11dip"
                android:layout_marginRight="10dip"
                android:layout_marginTop="35dip"
                android:layout_weight="1"
                android:background="@drawable/reset_stopwatch"
                android:text="@string/cancel_timing"
                android:textColor="#ffffffff"
                android:visibility="invisible" />
        </LinearLayout>
    </FrameLayout>

</LinearLayout>

WheelView.java
public class WheelView extends View {
	/**
     * 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);
    }
}

--->3.1
TimerFragment.java
    private void startCountTime(long millsecs) {

        mIsRunning = true;
        Intent intent = new Intent(mContext, TimerAlertActivity.class);  -->4.1 从这里设置闹钟提醒
        intent.putExtra("stop_time", millSecsToString(millsecs));   //传入闹钟时间
        mPendingIntent = PendingIntent.getActivity(mContext, 0,
                intent, Intent.FLAG_ACTIVITY_NEW_TASK);     

        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                Utils.getTimeNow() + millsecs, mPendingIntent);   //管理定时
                //以上设置闹钟
        mCountTimer = new CountTimer(millsecs, 100, mContext);   ---->3.2
        mCountTimer.start();   --->3.3

    }

---->3.2
public CountTimer(long millisInFuture, long countDownInterval, Context context) {
            super(millisInFuture, countDownInterval);    --->/*
            																									public CountDownTimer(long millisInFuture, long countDownInterval) {
																														        mMillisInFuture = millisInFuture;
																														        mCountdownInterval = countDownInterval;
																														    }
            																									*/
            mContext = context;
            mShowTiming.setText(millSecsToString(millisInFuture));

        }
        
--->3.3
frameworks/../CountDownTimer.java
/**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));   //msg.what = 1  -->3.4
        return this;
    }

-->3.4
CountDownTimer.java
// handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();    //完成倒计时退出   -->3.5
                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);   //在此进行倒计时
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);    -->3.9

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
    
     -->3.5
    TimerFragment.java
    class CountTimer extends CountDownTimer {
    
    public CountTimer(long millisInFuture, long countDownInterval, Context context) {
            super(millisInFuture, countDownInterval);
            mContext = context;
            mShowTiming.setText(millSecsToString(millisInFuture));

        }

        @Override
        public void onFinish() {
            mIsRunning = false;
            showPage(Utils.PAGE_SETUP_TIMER);
        }

			--->3.9
        @Override
        public void onTick(long millisUntilFinished) {
            mSecnum = millisUntilFinished;
            mShowTiming.setText(millSecsToString(millisUntilFinished));
        }
    }
    
    ---> 3.6
    TimerFragment.java
    private void showPage(int pageIndex) {
        if (pageIndex == Utils.PAGE_COUNTDOWN_TIMER) {
            mPageIndex = Utils.PAGE_COUNTDOWN_TIMER;
            showCountDownTimeView();   --> 3.7
        } else {
            mPageIndex = Utils.PAGE_SETUP_TIMER;
            showTimeSetupPage();   -->3.8
        }
    }
    
     --> 3.7
     //对fragment_timing.xml的显示界面做出反应
    private void showCountDownTimeView() {

        mStartBut.setVisibility(View.GONE);
        mShow.setVisibility(View.GONE);
        mTimePickerLayout.setVisibility(View.GONE);

        mShowTiming.setVisibility(View.VISIBLE);
        mCancelBut.setVisibility(View.VISIBLE);
        if (mIsRunning) {
            mStopBut.setVisibility(View.VISIBLE);
            mRestartBut.setVisibility(View.GONE);
        } else {
            mStopBut.setVisibility(View.GONE);
            mRestartBut.setVisibility(View.VISIBLE);
        }

    }
    
    当3.5完成时,也调用了showPage(Utils.PAGE_SETUP_TIMER);
    此时 -->3.8
    private void showTimeSetupPage() {
        mCancelBut.setVisibility(View.GONE);
        mStopBut.setVisibility(View.GONE);
        mShowTiming.setVisibility(View.GONE);
        mRestartBut.setVisibility(View.GONE);

        mStartBut.setVisibility(View.VISIBLE);
        mShow.setVisibility(View.VISIBLE);
        mTimePickerLayout.setVisibility(View.VISIBLE);
    }
    
    ---->4.1
    TimerAlertActivity.java
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.timer_alert);  --->4.2
        mContext = this; 
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        NotificationManager mNotificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(TimerFragment.TIMER_NOTIFI_ID);
        mHandler.post(mMediaRunnable);  -->设置Audio
        final Window win = getWindow();
        win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
        if (!getIntent().getBooleanExtra(SCREEN_OFF, false)) {
            win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
        }

        mTimerImg = (ImageView) findViewById(R.id.timer_anim);
        mTimerAnimation = (AnimationDrawable) mTimerImg.getBackground();   //设置动态播放动画
        String strStopTime = getIntent().getStringExtra("stop_time");
        TextView stop_time = (TextView) findViewById(R.id.timer_stop_time);
        if (strStopTime != null) {
            stop_time.setText(strStopTime);   //显示的是设置的最初时间
        } else {
            stop_time.setVisibility(View.GONE);
        }

        mCloseButton = findViewById(R.id.close_button);
        mCloseButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (v == mCloseButton) {
                    stopAnimation(mTimerAnimation);
                    finish();   //关闭闹钟   -->6.1 调用 onDestroy
                }
            }
        });

    }


protected void onResume() {   -->5.1
        super.onResume();
        mHandler.postDelayed(mRunnable, START_DELAY);
    }
    
     private Runnable mRunnable = new Runnable() { -->5.2
        public void run() {
            startAnimation(mTimerAnimation);
        }
    };
    
    
    protected void startAnimation(final AnimationDrawable animation) {
        if (animation != null && !animation.isRunning()) {
            animation.run();    -->5.3
        }
    }
    
    public void run() {
        nextFrame(false);    -->5.4   //持续播放闹钟
    }
    
    -->6.1
    protected void onDestroy() {
        super.onDestroy();
        if (mAlarm != null) {
            mAlarm.stop();
            mAlarm.release();
            mAlarm = null;
        }
        if (mAudioManager != null) {
            mAudioManager.abandonAudioFocus(mAudioFocusListener);
        }
    }

---->4.2
timer_alert.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black" >

    <ImageView
        android:id="@+id/timer_anim"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="37dp"
        android:layout_centerHorizontal="true"
        android:background="@anim/timer_time_up" />

    <TextView
        android:id="@+id/timer_stop_time"
        android:layout_width="wrap_content"
        android:layout_marginTop="9dp"
        android:layout_height="50dp"
        android:layout_below="@+id/timer_anim"
        android:layout_centerHorizontal="true"
        android:textColor="@android:color/white"
        android:textSize="41sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/timer_time_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/timer_stop_time"
        android:layout_marginTop="30dp"
        android:layout_centerHorizontal="true"
        android:text="@string/timer_timeup"
        android:textColor="#ffffffff"
        android:textSize="25sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/close_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="7dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:text="@string/timer_close"
        android:textColor="#ffffffff"
        android:textSize="20sp"
        android:background="@drawable/stop_stopwatch"
        android:textAppearance="?android:attr/textAppearance" />

</RelativeLayout>

private Runnable mMediaRunnable = new Runnable() {
        public void run() {
            mAlarm = new MediaPlayer();
            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.alarm);
            try {
                if (afd != null) {
                    mAlarm.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
                            afd.getLength());
                    afd.close();
                }
            } catch (Exception ex2) {
                // At this point we just don't play anything.
                Log.e(TAG, "Failed to play fallback alarm");
            }
            if (mAudioManager != null) {
                mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_ALARM,
                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
            }
            try {
                if (mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
                    mAlarm.setAudioStreamType(AudioManager.STREAM_ALARM);
                    mAlarm.setLooping(true);
                    mAlarm.prepare();
                    mAlarm.start();
                }
            } catch (Exception ex3) {
                Log.e(TAG, "Failed to prepare alarm");
            }
        }
    };

抱歉!评论已关闭.