倒计时时钟

来源:互联网 发布:微信机器人软件 编辑:程序博客网 时间:2024/06/04 19:42

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.javapublic 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.1fragment_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.javapublic 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.1TimerFragment.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.2public 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.3frameworks/../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.4CountDownTimer.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.2timer_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");            }        }    };