Always disable status bar and bottom bar in a cust

2019-08-31 09:39发布

问题:

I need to write custom android launcher with only one my application and with disabling android system statusbar and bottom bar. Here is my code

in AndroidManifest.xml

    <activity android:name=".MainActivity"
        android:launchMode="singleTask"
        android:stateNotNeeded="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER"/>
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

in styles.xml

 <item name="android:windowShowWallpaper">true</item>
 <item name="android:windowBackground">@android:color/transparent</item>

ins MainActivity.class

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        hideSystemUi()
        buttonStartMyApp.setOnClickListener {
            Toast.makeText(this@MainActivity, "Start own app", Toast.LENGTH_SHORT).show()
        }
    }

private fun hideSystemUi() {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    }

This launcher starts with only one button (its okay) and without status bar and bottom nav bar. BUT we can to get them with top-down swipe on the top of the screen. How to disable this function? Thanks.

回答1:

You have implemented the IMMERSIVE_STICKY flag which allows the status bar to be called by top-down swipe on the top of the screen. To disable this:

super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
setContentView(R.layout.your_layout);

To disable status drop down, use this method. This is an overlay over status bar and consumed all input events. It prevents the status from expanding.

Note:

customViewGroup is custom class which extends any layout(frame,relative layout etc) and consumes touch event. To consume touch event override the onInterceptTouchEvent method of the view group and return true.

Android Manifest

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 

customViewGroup implementation

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) (50 * getResources()
            .getDisplayMetrics().scaledDensity);
    localLayoutParams.format = PixelFormat.TRANSPARENT;

    customViewGroup view = new customViewGroup(this);

    manager.addView(view, localLayoutParams);


回答2:

Run a Service in background and just close the status bar always. For Oreo and above this is the only one solution I have found. For below versions we can use the above answer.

package your.package;
import java.lang.reflect.Method;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;

public class ServiceCloseBar extends Service {

    private static Timer timer;
    private static TimerTask task;
    private static int TIME_INTERVAL=100;
    @Override
    public void onCreate() {
        super.onCreate();
        try {
            timer=new Timer();
            task = new TimerTask() {
                public void run() {
                    try {
                        Object sbservice = getSystemService( "statusbar" );
                        Class<?> statusbarManager = Class.forName( "android.app.StatusBarManager" );
                        Method expandMethod;
                        if (Build.VERSION.SDK_INT >= 17) {
                            expandMethod = statusbarManager.getMethod("collapsePanels");
                        } else {
                            expandMethod = statusbarManager.getMethod("collapse");
                        }
                        expandMethod .invoke( sbservice );  
                    } catch (Exception e) {
                    };
                }
            };

            timer.scheduleAtFixedRate(task, 0, TIME_INTERVAL);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}