如果调用setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION),则不会触发onTouchEvent()

时间:2012-06-01 07:10:00

标签: android

我打电话

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) 

当我的应用开始让我的应用能够显示全屏时。

我希望在触摸屏幕时弹出我的应用程序UI,但在第二次触摸屏幕之前不会触发Activity.onTouchEvent()。首次触摸时,只显示虚拟键。

所以,我必须触发我的应用程序的UI才能弹出

public void onSystemUiVisibilityChange(int visibility) {
    if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) {
         // show my APP UI
    }
}

但系统会调用onSystemUiVisibilityChange View.SYSTEM_UI_FLAG_VISIBLE而不是每次触摸(我的Galaxy Nexus上3次),尤其是当用户非常快/经常触摸屏幕时。

项目lib 4.0或4.03。 三星Galaxy(9250)4.03。

8 个答案:

答案 0 :(得分:3)

Android 4.4(API级别19)为SYSTEM_UI_FLAG_IMMERSIVE引入了一个新的setSystemUiVisibility()标记,可让您的应用真正“全屏”。此标记与SYSTEM_UI_FLAG_HIDE_NAVIGATIONSYSTEM_UI_FLAG_FULLSCREEN标记结合使用时会隐藏导航和状态栏,并让您的应用捕获屏幕上的所有触摸事件。

答案 1 :(得分:1)

这对我有用:

 setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
        @Override
        public void onSystemUiVisibilityChange(int visibility) {
            if ((visibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
                // show my app UI
            }
        }
    });

答案 2 :(得分:1)

我所做的是先导入android.view.GestureDetector所以我可以用它来检测手势。 Android有许多默认手势,可在GestureDector class中自动检测到。大部分信息都是here,但下面是我在实际项目中使用的表单中的代码。

首先我在我的Activity中创建了一个匿名类(这可以嵌套在任何地方,但我倾向于在底部,在结束括号之前创建我的匿名类)。注意:您也可以在课程中实施OnGestureListener

以下代码用于使用手势检测来进行简单的隐藏/显示。

我已经声明并定义了我的操作栏(我的UI,最初是隐藏的)作为实例变量,所以我可以在这里访问它,无论在哪里,但你可以用getActionBar().show()代替它getActionBar().hide()如果您不想将其声明为实例变量。在actionBar此处替换您的用户界面:

public class Example extends ActionBarActivity {

    // declared in onCreate() method
    private android.support.v7.app.ActionBar actionBar; 
    private GestureDetectorCompat mDetector;
    private YourView view1;
    private YourView view2;
    private YourView view3;
    private YourView view4;

    // some other code

    class GestureListener extends GestureDetector.SimpleOnGestureListener {

    private static final String DEBUG_TAG = "Gestures in Example Class";

        @Override
        public boolean onDoubleTap(MotionEvent event) {

            Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());
            // if there is a double tap, show the action bar
            actionBar.show();

            return true;
       }

       @Override
       public boolean onSingleTapConfirmed(MotionEvent event) {

            Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());

            // if the tap is below the action bar, hide the action bar
            if (event.getRawY() > getResources().getDimension(R.dimen.abc_action_bar_default_height)) {
                actionBar.hide();
                return true;
            }

            return false;
        }

        @Override
        public boolean onDown(MotionEvent event) {

             return true;

        }

} // end-of-Example Class

然后在我的onCreate()我宣布了我的GestureDetector并且(可选)设置了我的GestureListeners

private GestureDetectorCompat mDetector;

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

    // some code here
    mDetector = new GestureDetectorCompat(this, new GestureListener());

    // this code is for more advanced view logic not needed for a basic set-up
    //setGestureListeners();

} // end-of-method onCreate()

然后,为了实际发送要处理的手势,我们提供了执行此操作的说明,我知道有两种方法,首先是最简单的方法:

/**
* This method recognizes a touchEvent and passes it to your custom GestureListener 
* class.
*/
@Override 
public boolean onTouchEvent(MotionEvent event){

     this.mDetector.onTouchEvent(event);

     return super.onTouchEvent(event);
}

第二种方式更复杂,但是如果您只想识别布局中某些View的触摸事件,就像您有重叠视图并且只能访问顶部View一样,您可以创建一个自定义类来围绕或向上传递事件:

class MyOnTouchListener implements View.OnTouchListener {

    public boolean onTouch(View v, MotionEvent event) {

        if (v.equals(view4)) {
            return mDetector.onTouchEvent(event);   
        } else return false;
    }
} // end-of-class MyOnTouchListener

然后在这里使用它:

public void setGestureListeners() {

    /* when we return false for any of these onTouch methods
    * it means that the the touchEvent is passed onto the next View.
    * The order in which touchEvents are sent to are in the order they
    * are declared.
    */
    view1.setOnTouchListener(new MyOnTouchListener());

    view2.setOnTouchListener(new MyOnTouchListener());

    view3.setOnTouchListener(new MyOnTouchListener());

    view4.setOnTouchListener(new MyOnTouchListener());


} // end-of-method setGestureListeners()

在我的setGestureListeners方法中,我给了他们所有相同的命令集,基本上只识别view4上的touchEvents。否则,它只是将touchEvent传递给下一个视图。

这是使用AppCompat的代码,但如果您不是针对旧版本构建,则可以使用常规GestureDetectorActionBar

答案 3 :(得分:0)

您是否尝试过添加代码以仅在状态发生变化时显示您的用户界面?您必须保持最后的已知可见性,并且只有在您第一次看到时才会显示您的用户界面:

int mLastSystemUiVis;

@Override 
public void onSystemUiVisibilityChange(int visibility) {
    int diff = mLastSystemUiVis ^ visibility;
    mLastSystemUiVis = visibility;
    if ((diff&SYSTEM_UI_FLAG_VISIBLE) != 0
            && (visibility&SYSTEM_UI_FLAG_VISIBLE) == 0) {
        // DISPLAY YOUR UI
    }
}

Android docs

采用的代码示例

答案 4 :(得分:0)

我也遇到了这个问题,我找到了http://developer.android.com/reference/android/view/View.html#SYSTEM_UI_FLAG_HIDE_NAVIGATION

所以,没办法帮忙。甚至android系统打包的Gallery应用程序在照片页面视图中使用SYSTEM_UI_FLAG_LOW_PROFILE而不是SYSTEM_UI_FLAG_HIDE_NAVIGATION。这至少是我们能做的。

答案 5 :(得分:0)

我有一个非常类似的问题,试图从onTouchEvent()更新UI需要两次触摸工作,我尝试了一堆精心设计的东西,最后让它在第一次点击时工作。

在我的情况下,我显示了一个先前隐藏的项目,然后获得它的高度,然后向下移动该高度的按钮。我遇到的问题是高度显示为0,直到第一次触摸事件结束。我能够通过在ACTION_UP期间为onTouchEvent()而不是ACTION_DOWN调用show()来解决此问题。也许如果你做了类似的事情它会起作用吗?

答案 6 :(得分:0)

尝试使用:

getWindow()getDecorView()setSystemUiVisibility(View.GONE);

代替:

getWindow()。getDecorView()。setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)

之后,您可以全屏使用常规活动,如果您需要导航键,则需要从下往上滑动。使用android 4.1.2在Galaxy Tab 2上为我工作

答案 7 :(得分:-1)

方法Activity.onTouchEvent()在响应者链的 end 处被调用(意味着在所有其他视图都有机会使用该事件之后)。如果您点按了对触摸感兴趣的视图(即ButtonEditText),那么您的活动很可能永远不会看到该事件。

如果您希望在每次调度到视图之前都有权访问,请改写Activity.dispatchTouchEvent(),这是 开头 < / strong>事件链:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    //Check the event and do magic here, such as...
    if (event.getAction() == MotionEvent.ACTION_DOWN) {

    }

    //Be careful not to override the return unless necessary
    return super.dispatchTouchEvent(event);
}

请注意不要覆盖此方法的返回值,除非您有意想从其他视图中窃取触摸,此位置中不必要的return true;将破坏其他触摸处理。