【问题标题】:How to use the back press to remove the view added by WindowManager?WindowManager添加的view怎么用back press去掉?
【发布时间】:2014-12-30 07:50:21
【问题描述】:

各位,我正在开发一个android AppLock 应用程序,我使用WindowManager 添加手势锁定视图。 但我有一个问题。 后退键不会删除视图。 而且我不能重写视图来覆盖 dispatchKeyEvent() 函数,因为我使用 LayoutInflater 来膨胀我的视图。就这样:

LayoutInflater layoutInflater = 
            (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
enterPassView = layoutInflater.inflate(R.layout.activity_enterpass, null);

请帮我解决这个问题! 谢谢。


加入UTC+8 2014/12/31 18:20

你好,我很高兴我用一种简单的方法来解决我的问题。我使用了两个标志变量,一个是viewFlag(当我调用addView()时,viewFlag = true;当我调用removeView()时,viewFlag = false),另一个是lockedFlag(当顶部App被用户锁定时数据库,lockedFlag = true,未锁定时,lockedFlag = false) 所以,if(lockedFlag == false && viewFlag == true && view != null) { //我向处理程序发送消息以调用 removeView( ) }


class EnterPassView extends View {

    public EnterPassView(Context context) {
        super(context);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            Message message = viewHandler.obtainMessage(0);
            viewHandler.sendMessage(message);
            return super.dispatchKeyEvent(event);
        } else if(event.getKeyCode() == KeyEvent.KEYCODE_HOME) {
            Message message = viewHandler.obtainMessage(0);
            viewHandler.sendMessage(message);
            return super.dispatchKeyEvent(event);
        } else if(event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
            Message message = viewHandler.obtainMessage(0);
            viewHandler.sendMessage(message);
            return super.dispatchKeyEvent(event);
        }
        return super.dispatchKeyEvent(event);
    }

}

private void showGestureLockView() {
    params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT, 
            WindowManager.LayoutParams.MATCH_PARENT, 
            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 
            WindowManager.LayoutParams.FLAG_FULLSCREEN | 
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
            PixelFormat.RGBA_8888);
    params.gravity = (Gravity.CENTER);

    LayoutInflater layoutInflater = 
            (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    enterPassView = layoutInflater.inflate(R.layout.activity_enterpass, null);

    iv_icon = (ImageView) enterPassView.findViewById(R.id.enterpass_iv_icon);
    tv_text = (TextView) enterPassView.findViewById(R.id.enterpass_tv_text);

    animation = new TranslateAnimation(-20, 20, 0, 0);
    animation.setDuration(50);
    animation.setRepeatCount(2);
    animation.setRepeatMode(Animation.REVERSE);

    SharedPreferences sp = getSharedPreferences(AppConfig.APP_SP_NAME, MODE_PRIVATE);
    String savePass = sp.getString(AppConfig.GESTURE_PASS, "");
    gesturePassView = (GesturePassView) enterPassView.findViewById(R.id.enterpass_view_gpv);
    gesturePassView.setSavedPass(savePass);
    gesturePassView.setScene(0);
    gesturePassView.setOnGestureCompleteListener(new OnGestureCompleteListener() {

        @Override
        public void onGestureComplete(int result, String enterPassword) {
            if(result == 0) {
                iv_icon.setAnimation(animation);
                tv_text.setText(R.string.enterpass_lesspass);
            } else if(result == 1){
                Message message = viewHandler.obtainMessage(0);
                viewHandler.sendMessage(message);
                Log.e("sendMessage", "pass is true want to remove view");
            } else if(result == -1){
                iv_icon.setAnimation(animation);
                tv_text.setText(R.string.enterpass_wrongpass);
            }
        }
    });

    if(windowsManager == null) {
        windowsManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    }
    if(windowsManager != null && enterPassView != null) {
        Message message = viewHandler.obtainMessage(1);
        viewHandler.sendMessage(message);
        Log.e("sendMessage", "want to addView");
    }

}

Handler viewHandler = new Handler() {

    @Override
    public void handleMessage(Message message) {
        int flag = message.what;
        if(flag == 1) {
            windowsManager.addView(enterPassView, params);
            Log.e("sendMessage", "addView");
        } else if(flag == 0) {
            windowsManager.removeView(enterPassView);
            enterPassView = null;
            Log.e("sendMessage", "removeView");
        }

    }

};

【问题讨论】:

    标签: android


    【解决方案1】:

    这是一个可以提供帮助的伪代码。

    1. 在你的视图中创建一个调用这个的公共方法:

      windowsManager.removeView(enterPassView);

    2. 然后在您的活动中覆盖 onBackPressed。 http://developer.android.com/reference/android/app/Activity.html#onBackPressed()

    3. 在覆盖的 onBackPressed 中调用您在自定义 View 类中创建的方法。做一个 try catch 语句:

      试试{ YourView.removeWindowView() }catch(IllegalArgumentException e){ //如果它出现在此处,则意味着没有要从 windowsManager 中删除的视图 - 在这种情况下调用 super.onBackPressed(); }

    编辑。下面是解决问题的代码:

    public class MainActivity extends Activity {
        private MyService mServer;
        ServiceConnection mConnection = new ServiceConnection() {
    
            public void onServiceDisconnected(ComponentName name) {
    
            }
    
            public void onServiceConnected(ComponentName name, IBinder service) {
    
                LocalBinder mLocalBinder = (LocalBinder) service;
                mServer = mLocalBinder.getServerInstance();
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(MainActivity.this, MyService.class);
            bindService(intent, mConnection, BIND_AUTO_CREATE);
    
        }
        @Override
        public void onBackPressed() {
            try{
                mServer.removeWindow();
            }
            catch(IllegalArgumentException e){
                super.onBackPressed();
            }
    
    
        }
    
    }
    
    public class MyService extends Service {
    
        Thread thread;
        WindowManager windowsManager = null;
        WindowManager.LayoutParams params;
        View view;
    
        IBinder mBinder = new LocalBinder();
    
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        public class LocalBinder extends Binder {
            public MyService getServerInstance() {
                return MyService.this;
            }
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            new Handler().postDelayed(new Runnable() {
    
                @Override
                public void run() {
                    showView();
                }
    
            }, 5000);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
        }
    
        private void showView() {
            params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.MATCH_PARENT, 
                    WindowManager.LayoutParams.MATCH_PARENT, 
                    WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 
                    WindowManager.LayoutParams.FLAG_FULLSCREEN | 
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
                    PixelFormat.RGBA_8888);
            params.gravity = (Gravity.CENTER);
            LayoutInflater layoutInflater = 
                    (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = layoutInflater.inflate(R.layout.view_service, null);
            if(windowsManager == null) {
                windowsManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
            }
            if(windowsManager != null && view != null) {
                Message message = addViewHandler.obtainMessage(1);
                addViewHandler.sendMessage(message);
            }
    
        }
    
        Handler addViewHandler = new Handler() {
    
            @Override
            public void handleMessage(Message message) {
                int flag = message.what;
                if(flag == 1) {
                    windowsManager.addView(view, params);
                } else if(flag == 0) {
                    windowsManager.removeView(view);
                }
            }
        };
        public void removeWindow(){
            windowsManager.removeView(view);
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,但问题是我使用 WindowManager 添加带有服务的视图,因为我想收听我锁定的应用程序。所以,没有Activity。对不起,我的英语很差。
    • 好的,现在我更好地理解了情况,代码现在会发生什么,它失败了吗?
    • 有日志:12-30 11:36:23.213: E/AndroidRuntime(2616): FATAL EXCEPTION: Thread-238 12-30 11:36:23.213: E/AndroidRuntime(2616) : java.lang.ClassCastException: android.widget.LinearLayout 不能转换为 com.josephus.service.AppLockService$EnterPassView
    • 您的 EnterPassView 无法转换为 LinearLayout 它扩展了 View。但是您还没有添加发生此错误的代码。
    • 我刚刚找到了解决的方法,也许不是最好的,我只是想和大家分享一下。无论是“com.android.launcher”还是“com.android.systemui”,我都可以监听最上面运行的任务,如果为真,我调用removeView() 来移除WindowManager 添加的视图。现在我只是为了测试这个方法来发现错误。
    【解决方案2】:

    代码sn-ps不足以理解和回答最好的。 想到的是在您的视图中附加一个 keylistener 并在处理事件时说 ((ViewGroup)enterPassView.getParent()).removeView(enterPassView );

    【讨论】:

    • 我尝试重写视图并附加一个keyListener来处理后按事件,但是一旦我重写视图,应用程序就出错了。我知道使用removeView(),但问题是在哪里使用这个函数()?
    • 我把我的代码放在了页面上,请看代码帮帮我,这是我的毕业作品,我努力做到最好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2014-08-05
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 2018-09-13
    • 2019-03-08
    相关资源
    最近更新 更多