2011-04-28 30 views
3

我已经开发了一些实现计时器的代码 - 它每秒钟都会触发一次,并在未触摸显示器的x秒后启动“空闲”活动。 但是,这需要执行大约8个活动......我可以将相关代码复制并粘贴到每个活动,但这不是一个优雅的解决方案。扩展活动以实现空闲计时器

因此,我开始创建自定义活动“TimedActivity”来扩展Activity。然后,我需要实现的其他活动可以实现“TimedActivity”。

但是,我的TimedActivity如何检测onTouch事件?

这是我到目前为止有:

public class TimedActivity extends Activity implements OnTouchListener 
{ 
    private LinearLayout mLinearLayoutMain;//intended to be the root node in the XML 
    private Timer mTimerSeconds; 
    private int mIntIdleSeconds; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     //NO setContentView() 

     mIntIdleSeconds=0; 

     mTimerSeconds = new Timer(); 
     mTimerSeconds.schedule(new TimerTask() 
     { 
      @Override 
      public void run() 
      { 
       timerSecondsCounter(); 
      } 
     }, 0, 1000); 

     //the whole screen should become sensitive to touch 
     //HOWEVER, there's no View established 
     mLinearLayoutMain = (LinearLayout) findViewById(R.id.layout_main); 
     //mLinearLayoutMain remains null, so next line excepts 
     mLinearLayoutMain.setOnTouchListener(this); 
    } 


    @Override 
    protected void onDestroy() 
    { 
     if (mTimerSeconds != null) 
     { 
      mTimerSeconds.cancel(); 
     } 
     super.onDestroy(); 
    } 


    public boolean onTouch(View v, MotionEvent event) 
    { 
     mIntIdleSeconds=0; 
     return false;//do not consume 
    } 

    private void timerSecondsCounter() 
    { 
     mIntIdleSeconds++; 

     if (mIntIdleSeconds == Constants.MAX_IDLE_TIME_SECONDS) 
     { 
      final Intent intent = new Intent(this, what.ever.com.Idle.class); 
      startActivity(intent); 
     } 
    } 
} 

后续活动使用此,然后将使用:

public class ActivitySelect extends TimedActivity 
{ 
} 

和视图的XML是:

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:id="@+id/layout_main"> 

<!-- MORE STUFF ---> 

</LinearLayout> 

我觉得我很接近,但是我需要做些什么来实现这个目标?

编辑: 这是我最终实现...

public class TimedActivity extends Activity 
{ 
    //member variables 
    private Timer mTimerSeconds; 
    private int mIntIdleSeconds; 
    private boolean mBoolInitialized=false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    protected void onDestroy() 
    { 
     if (mTimerSeconds != null) 
     { 
      mTimerSeconds.cancel(); 
     } 
     super.onDestroy(); 
    } 

    public void onTouch() 
    { 
     mIntIdleSeconds=0; 
    } 

    /** start the idle timer */ 
    public void startIdleTimer() 
    { 
     if (mBoolInitialized == false) 
     { 
      mBoolInitialized = true; 

      //initialize idle counter 
      mIntIdleSeconds=0; 

      //create timer to tick every second 
      mTimerSeconds = new Timer(); 
      mTimerSeconds.schedule(new TimerTask() 
      { 
       @Override 
       public void run() 
       { 
        timerSecondsCounter(); 
       } 
      }, 0, 1000); 
     } 
    } 

    /** called every second to count idle time and to update clock on Welcome screen */ 
    private void timerSecondsCounter() 
    { 

     mIntIdleSeconds++; 

     if (mIntIdleSeconds == Constants.MAX_IDLE_TIME_SECONDS) 
     { 
      //idle time long enough to launch standby activity 
      final Intent intent = new Intent(this, what.ever.com.Idle.class); 
      startActivity(intent); 
     } 

    } 

} 

要在启动的活动中使用该ActivityTimed,这样做:

public class ActivitySelect extends TimedActivity implements OnTouchListener 
{ 
    //UI references 
    private LinearLayout mLinearLayout; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState);//triggers TimedActivity::onCreate() 
     setContentView(R.layout.select); 

     //get references to all of your widgets 
     mLinearLayout = (LinearLayout) findViewById(R.id.select_linearlayout_main); 

     //set your widgets as touchable 
     mLinearLayout.setOnTouchListener(this); 

     //start the idle timer 
     super.startIdleTimer(); 
    } 

    @Override 
    protected void onDestroy() 
    { 
     //this is very important here ;-) 
     super.onDestroy(); 
    } 

    public boolean onTouch(View v, MotionEvent event) 
    { 
     final int actionPerformed = event.getAction(); 

     //reset idle timer 
     // put this here so that the touching of empty space is captured too 
     // it seems that LinearLayout doesn't trigger a MotionEvent.ACTION_UP or MotionEvent.ACTION_MOVE 
     if (actionPerformed == MotionEvent.ACTION_DOWN) 
     { 
      super.onTouch(); 
     } 

     return false;//do not consume event! 
    } 
} 
+0

onTouch()方法使用@Override这是超时到期somekind的会话,或发送用户登录画面?如果是我遇到同样的问题,并有不同的解决方案。 – neteinstein 2011-04-28 17:31:11

+0

是的,一旦超时发生,一个不同的活动会自动启动 - 例如登录屏幕,屏幕保护程序等...一些空闲屏幕 – 2011-04-28 20:01:02

+0

然后,您可以通过使用默认属性来避免此方法:finishOnTaskLaunch除了Login外(登录活动不能完成并且必须在堆栈上 您还可以检测屏幕是否被关闭,并立即发送到登录屏幕 – neteinstein 2011-04-29 10:46:00

回答

0

编辑: OK,我之前试图建议的并不完全是我的意思......

ActivitySelectonCreate()方法(例如)把代码...

setContentView(/* Id of layout file for ActivitySelect */); 
mLinearLayoutMain = (LinearLayout) findViewById(/* Id of LinearLayout for ActivitySelect */); 

这将意味着ActivitySelect将设置其内容视图,并且还设置继承mLinearLayoutMain构件的视图。

onStart()TimedActivity放...

mLinearLayoutMain.setOnTouchListener(this); 

您可能还需要在TimedActivity

+0

同时吃午餐我认为通过在TimedActivity中实现一个函数(如“setViewRoot”),可能需要将LinearLayout的引用传递给超类(TimedActivity)。然后用super.setViewRoot(引用LinearLayout)来调用它;午餐后我会尝试。 – 2011-04-28 19:10:06

+0

@Someone:查看我编辑的答案 – Squonk 2011-04-28 21:43:27

+0

我最终做的并不是将LinearLayout的引用传递给TimedActivity。相反,我只在TimedActivity中实现了时序逻辑,而在onTouch()中实现了无效。这个onTouch()负责将计数器重置为0.然后,ActivitySelect扩展了TimedActivity实现的OnTouchListener。所有的onTouch(视图v,MotionEvent事件)回调然后调用super.onTouch();这很好,并且尽可能地保持代码解耦。 – 2011-04-28 23:58:35