私はロック画面アプリで作業しており、画面上部の通知/ステータスバーをプルダウンする機能を無効にする必要があります。 Holo Lockerと呼ばれるアプリがあり、このアプリはユーザーが画面の上部からプルダウンすると、バーを画面の上部に戻し、引き出しを引き下げることができなくなります。
どこから始めればいいのかわかりません。どんな助けでも素晴らしいです!ありがとう!
これは反射を使用して可能です。しかし、問題はたくさんあります。
通知パネルが開いているか、開いているかを確認する方法はありません。したがって、Activity#onWindowFocusChanged(boolean)
に依存する必要があります。そして、これが問題の始まりです。
メソッドの機能:
public void onWindowFocusChanged(boolean hasFocus)
アクティビティの現在のウィンドウがフォーカスを取得または失ったときに呼び出されます。これは、このアクティビティがユーザーに表示されるかどうかを示す最良のインジケータです。
したがって、通知パネルの表示によるフォーカスの喪失と他のイベントによるフォーカスの喪失を区別する方法を理解する必要があります。
onWindowFocusChanged(boolean)
をトリガーするいくつかのイベント:
アクティビティがバックグラウンドに送信されると、ウィンドウのフォーカスが失われる(ユーザーがアプリを切り替えるか、home
ボタンを押す)
DialogsとPopupWindowsはそれぞれ別のウィンドウで開くため、これらが表示されると、アクティビティのウィンドウフォーカスが失われます。
アクティビティのウィンドウがフォーカスを失う別の例は、スピナーがクリックされ、PopupWindowが表示される場合です。
あなたの活動はこれらの問題のすべてに対処する必要がないかもしれません。次の例は、それらのサブセットを処理します。
まず、_EXPAND_STATUS_BAR
_権限が必要です。
_<uses-permission Android:name="Android.permission.EXPAND_STATUS_BAR" />
_
次に、これらのクラススコープ変数をアクティビティで宣言します。
_// To keep track of activity's window focus
boolean currentFocus;
// To keep track of activity's foreground/background status
boolean isPaused;
Handler collapseNotificationHandler;
_
オーバーライドonWindowFocusChanged(boolean)
:
_@Override
public void onWindowFocusChanged(boolean hasFocus) {
currentFocus = hasFocus;
if (!hasFocus) {
// Method that handles loss of window focus
collapseNow();
}
}
_
定義collapseNow()
:
_public void collapseNow() {
// Initialize 'collapseNotificationHandler'
if (collapseNotificationHandler == null) {
collapseNotificationHandler = new Handler();
}
// If window focus has been lost && activity is not in a paused state
// Its a valid check because showing of notification panel
// steals the focus from current activity's window, but does not
// 'pause' the activity
if (!currentFocus && !isPaused) {
// Post a Runnable with some delay - currently set to 300 ms
collapseNotificationHandler.postDelayed(new Runnable() {
@Override
public void run() {
// Use reflection to trigger a method from 'StatusBarManager'
Object statusBarService = getSystemService("statusbar");
Class<?> statusBarManager = null;
try {
statusBarManager = Class.forName("Android.app.StatusBarManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method collapseStatusBar = null;
try {
// Prior to API 17, the method to call is 'collapse()'
// API 17 onwards, the method to call is `collapsePanels()`
if (Build.VERSION.SDK_INT > 16) {
collapseStatusBar = statusBarManager .getMethod("collapsePanels");
} else {
collapseStatusBar = statusBarManager .getMethod("collapse");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
collapseStatusBar.setAccessible(true);
try {
collapseStatusBar.invoke(statusBarService);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
// Check if the window focus has been returned
// If it hasn't been returned, post this Runnable again
// Currently, the delay is 100 ms. You can change this
// value to suit your needs.
if (!currentFocus && !isPaused) {
collapseNotificationHandler.postDelayed(this, 100L);
}
}
}, 300L);
}
}
_
アクティビティのonPause()
およびonResume()
を処理します。
_@Override
protected void onPause() {
super.onPause();
// Activity's been paused
isPaused = true;
}
@Override
protected void onResume() {
super.onResume();
// Activity's been resumed
isPaused = false;
}
_
これがあなたが探しているものに近いことを願っています。
注:通知バーをスライドして押し続けると発生するフリッカーは、残念ながら避けられません。ただし、その外観はハンドラー遅延の「より良い」値を使用して制御/改善できます。この問題は、Holo Lockerアプリにも存在します。
private void disablePullNotificationTouch() {
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (25 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.RGBX_8888;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
}
//Add this class in your project
public class customViewGroup extends ViewGroup {
public customViewGroup(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "**********Intercepted");
return true;
}
ユーザーがステータスを開けないようにしたい場合は、これを試してください:
getWindow().addFlags(WindowManager.LayoutParams.[TYPE_SYSTEM_OVERLAY][1]);
使用法 :
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
setContentView(R.layout.your_layout);
前に追加する特定のニーズに基づいて、適切な WindowManager.LayoutParams を選択できます。
お役に立てれば。
受け入れられた答えを試しましたが、それでも、いくつかの設定をプルダウンしてすばやく変更することができました。
別の解決策 があります。これにより、ユーザーがメニューを完全にプルダウンできなくなります。これは、ここで受け入れられる回答よりも優先されます。
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags =
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (40 * getResources().getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
blockingView = new CustomViewGroup(this);
manager.addView(blockingView, localLayoutParams);
これを行って、クラスcustomViewGroupの link を参照してください