一个简单的Android开源生产力计时器应用程序
发布时间:2025-05-13 21:56:04 发布人:远客网络
一、一个简单的Android开源生产力计时器应用程序
保持注意力集中,摆脱分心,安排好工作时间。好的工具可以帮助我们提高生产力。Goodtime(美好时光)是一款面向Android用户,极简主义的pomodoro计时器应用程序。它是免费开源的,具有简单有效的计时技术,帮助用户查看进度,保持专注。用户界面简洁,仅需几个手势即可操作。例如,轻触计时器启动,从通知区域停止。您可调整计时器持续时间,设置理想的工作和休息时间。当计时器结束时,会发出警报通知您休息,可自动重新启动(若已启用)。应用程序会跟踪进度,评估时间管理情况,促进自律。专业订阅解锁额外功能,如首次启动应用的手势教程。下载并安装Goodtime,可在Google Play商店、F-Driod和Github上获取。这款应用程序是否满足了您的需求?或者,您会推荐一个更好的实用程序来提高Android的生产力吗?欢迎在评论中分享您的见解!
二、android 实现同时多个倒计时效果怎么做
1、安卓实现同时多个倒计时效果的步骤:
2、我们首先需要在输入框中输入一个秒数,比如:12,然后获取输入框中的值,显示在一个TextView中;
3、点击“开始倒计时”按钮,每隔一秒钟,秒数减1,然后显示在TextView中;
4、点击“停止倒计时”按钮,计时器停止运行,当再次点击“开始倒计时”按钮,计时器继续运行。
5、平时用的每个商品都应该有两个属性值,这里叫它deadLine和isOverdue吧,表示商品的到期时间和是否到期,那么倒计时可以考虑这么实现:设置一个主计时器,每隔1秒发出消息告诉GridView现在的时间,GridView的Item获得这个时间之后就和deadLine比较,如果已经到deadline了,就把数据源中的这项标记成已到期(修改isOverdue的值为true);没到deadline,就计算还差多少时间,显示到GridView的Item里。
三、Android编程中chronometer在后台怎么才能定时暂停
我看了下Chronometer这个类的源码,他内部就是用一个handler延迟一秒给自己发送一次消息,然后修改时间。按Home键,会触发Chronometer的onWindowVisibilityChanged()方法
上面方法是启动计时器,将mStarted变量设置为true,并执行一次updateRunning()方法,updateRunning()会在下面讲到
stop()方法是停止计时,将mStarted变量设置为false,并执行一次updateRunning()方法
protectedvoidonWindowVisibilityChanged(intvisibility){
super.onWindowVisibilityChanged(visibility);
上面的onWindowVisibilityChanged方法,是View里面的方法,只要View的可见状态发生改变了都会触发这个方法,很显然你说按Home键时间没停止,就是因为这个方法里面的代码,实际上是因为按Home键触发这个方法以后,就不再回调你设置的监听器的回调方法。按Home键后,View变为不可见状态,变量mVisible变成了false
booleanrunning=mVisible&&mStarted;
updateText(SystemClock.elapsedRealtime());
mHandler.sendMessageDelayed(Message.obtain(mHandler,TICK_WHAT),1000);
mHandler.removeMessages(TICK_WHAT);
上面的updateRunning()方法主要是工具mVisible和mStarted这2个boolean变量来控制是否向handler发送消息。
privateHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagem){
updateText(SystemClock.elapsedRealtime());
sendMessageDelayed(Message.obtain(this,TICK_WHAT),1000);
这个Handler主要是执行dispatchChronometerTick()方法再向它自己发送一条延时消息
voiddispatchChronometerTick(){
if(mOnChronometerTickListener!=null){
mOnChronometerTickListener.onChronometerTick(this);
dispatchChronometerTick()方法就是回调你设置的监听器的onChronometerTick方法
根据以上分析,按Home键之后,Chronometer就不会回调你的监听器方法,这个是受Chronometer的onWindowVisibilityChanged()方法控制的,所以你的问题不好解决!!
我能想到的解决方式就是把Chronometer的代码拿过来,自己写一个类,粘贴上Chronometer里面的代码,然后再修改它的onWindowVisibilityChanged()方法,然后就可以用自己的这个计时器了。我测试过了,实现了
最后附上我自己的MyChronometer类代码,你可以复制一下。。在布局文件里直接用这个控件
packagecom.lily.demo_listview;
*Copyright(C)2008TheAndroidOpenSourceProject
*LicensedundertheApacheLicense,Version2.0(the"License");
*youmaynotusethisfileexceptincompliancewiththeLicense.
*YoumayobtainacopyoftheLicenseat
*
*Unlessrequiredbyapplicablelaworagreedtoinwriting,software
*distributedundertheLicenseisdistributedonan"ASIS"BASIS,
*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
*SeetheLicenseforthespecificlanguagegoverningpermissionsand
importjava.util.IllegalFormatException;
importandroid.annotation.SuppressLint;
importandroid.content.Context;
importandroid.text.format.DateUtils;
importandroid.util.AttributeSet;
importandroid.view.accessibility.AccessibilityEvent;
importandroid.view.accessibility.AccessibilityNodeInfo;
importandroid.widget.RemoteViews.RemoteView;
importandroid.widget.TextView;
*Classthatimplementsasimpletimer.
*Youcangiveitastarttimeinthe{@linkSystemClock#elapsedRealtime}timebase,
*anditcountsupfromthat,orifyoudon'tgiveitabasetime,itwillusethe
*timeatwhichyoucall{@link#start}.Bydefaultitwilldisplaythecurrent
*timervalueintheform"MM:SS"or"H:MM:SS",oryoucanuse{@link#setFormat}
*toformatthetimervalueintoanarbitrarystring.
*@attrrefandroid.R.styleable#Chronometer_format
publicclassMyChronometerextendsTextView{
privatestaticfinalStringTAG="Chronometer";
*Acallbackthatnotifieswhenthechronometerhasincrementedonitsown.
publicinterfaceOnChronometerTickListener{
*Notificationthatthechronometerhaschanged.
voidonChronometerTick(MyChronometerchronometer);
privateLocalemFormatterLocale;
privateObject[]mFormatterArgs=newObject[1];
privateStringBuildermFormatBuilder;
privateOnChronometerTickListenermOnChronometerTickListener;
privateStringBuildermRecycle=newStringBuilder(8);
privatestaticfinalintTICK_WHAT=2;
*InitializethisChronometerobject.
publicMyChronometer(Contextcontext){
*Initializewithstandardviewlayoutinformation.
publicMyChronometer(Contextcontext,AttributeSetattrs){
*Initializewithstandardviewlayoutinformationandstyle.
publicMyChronometer(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
//TypedArraya=context.obtainStyledAttributes(
//com.android.internal.R.styleable.Chronometer,defStyle,0);
//setFormat(a.getString(com.android.internal.R.styleable.Chronometer_format));
mBase=SystemClock.elapsedRealtime();
*Setthetimethatthecount-uptimerisinreferenceto.
*@parambaseUsethe{@linkSystemClock#elapsedRealtime}timebase.
Log.d("MyChronometer","dispatchChronometerTick333");
updateText(SystemClock.elapsedRealtime());
*Returnthebasetimeassetthrough{@link#setBase}.
*Setstheformatstringusedfordisplay.TheChronometerwilldisplay
*thisstring,withthefirst"%s"replacedbythecurrenttimervaluein
*Iftheformatstringisnull,orifyounevercallsetFormat(),the
*Chronometerwillsimplydisplaythetimervaluein"MM:SS"or"H:MM:SS"
publicvoidsetFormat(Stringformat){
if(format!=null&&mFormatBuilder==null){
mFormatBuilder=newStringBuilder(format.length()*2);
*Returnsthecurrentformatstringassetthrough{@link#setFormat}.
*Setsthelistenertobecalledwhenthechronometerchanges.
publicvoidsetOnChronometerTickListener(OnChronometerTickListenerlistener){
mOnChronometerTickListener=listener;
*@returnThelistener(maybenull)thatislisteningforchronometerchange
publicOnChronometerTickListenergetOnChronometerTickListener(){
returnmOnChronometerTickListener;
*Startcountingup.Thisdoesnotaffectthebaseassetfrom{@link#setBase},just
*Chronometerworksbyregularlyschedulingmessagestothehandler,evenwhenthe
*Widgetisnotvisible.Tomakesureresourceleaksdonotoccur,theusershould
*makesurethateachstart()callhasareciprocalcallto{@link#stop}.
*Stopcountingup.Thisdoesnotaffectthebaseassetfrom{@link#setBase},just
*Thisstopsthemessagestothehandler,effectivelyreleasingresourcesthatwould
*beheldasthechronometerisrunning,via{@link#start}.
*Thesameascalling{@link#start}or{@link#stop}.
*@hidependingAPIcouncilapproval
publicvoidsetStarted(booleanstarted){
protectedvoidonDetachedFromWindow(){
super.onDetachedFromWindow();
Log.d("MyChronmeter","onDetachedFromWindow()"+mVisible);
protectedvoidonWindowVisibilityChanged(intvisibility){
super.onWindowVisibilityChanged(visibility);
privatesynchronizedvoidupdateText(longnow){
Stringtext=DateUtils.formatElapsedTime(mRecycle,seconds);
Localeloc=Locale.getDefault();
if(mFormatter==null||!loc.equals(mFormatterLocale)){
mFormatter=newFormatter(mFormatBuilder,loc);
mFormatter.format(mFormat,mFormatterArgs);
text=mFormatBuilder.toString();
}catch(IllegalFormatExceptionex){
Log.w(TAG,"Illegalformatstring:"+mFormat);
updateText(SystemClock.elapsedRealtime());
Log.d("MyChronometer","dispatchChronometerTick222");
mHandler.sendMessageDelayed(Message.obtain(mHandler,TICK_WHAT),1000);
mHandler.removeMessages(TICK_WHAT);
privateHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagem){
updateText(SystemClock.elapsedRealtime());
Log.d("MyChronometer","dispatchChronometerTick111");
sendMessageDelayed(Message.obtain(this,TICK_WHAT),1000);
voiddispatchChronometerTick(){
if(mOnChronometerTickListener!=null){
mOnChronometerTickListener.onChronometerTick(this);
//Log.d("MyChronometer","回调方法");
@SuppressLint("NewApi")@Override
publicvoidonInitializeAccessibilityEvent(AccessibilityEventevent){
super.onInitializeAccessibilityEvent(event);
event.setClassName(MyChronometer.class.getName());
@SuppressLint("NewApi")@Override
publicvoidonInitializeAccessibilityNodeInfo(AccessibilityNodeInfoinfo){
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(MyChronometer.class.getName());