AndroidのTranslucent Bar半透明バーとimmersive bar浸透式の違い

20695 ワード

AndroidのMaterial Designが登場した後、より簡潔で快適で、よりさわやかなインタフェースは開発者たちが求めていることであり、成功したappの前提でもある.では、appをより快適に見せるにはどうすればいいのでしょうか.ここに方法があります.
  はappを全体的に統一しているように見えます.全体的に統一するという意味です.どのように一体化するのか、2つの方法があります.ネット上では2つの異なる方法についてよく混同されていますが、両者は一体化の概念です.
  1. Translucent bar(半透明のステータスバー):ステータスバーとナビゲーションバーは半透明で、appのスタイルに合わせて色を調整し、appのコンテンツスタイルと融合することができます.これはGoogleがSDK 19で提案した概念であり、apiを増やすことで一定のサポートを行っている.このブログでは、Translucent bar-DyeingBarHelperをより便利に操作できるツールクラスを提供しています.
  2. 浸漬ステータスバー:ステータスバーとナビゲーションバーがなく、appを画面に完全に表示します.
字面上の意味からこの2つのパターンの違いを大まかに区別することができ,以下にも例を通してより直感的な説明を行い,同時に1つの実現を行う.引き続き見る前に、Status Bar(最上部のバッテリーWi-Fi情報のある欄)とNavigationBar(下部の戻りキー、homeキー、menuキー、これはすべての機にあるものではなく、主に画面内にあるか、スクリーン外に独立しているか)を理解しておきましょう.
Tanslucent Barの実装-DyeingBarHelper(倉庫アドレス)
このモードの主な効果はappの全体的なスタイルを一致させ、よりさっぱりしていて、快適で、インタフェースが統一されているように見えます.Androidの19の後には、ステータスバーを半透明に設定する方法があります.
//   Navigtion bar   
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
//   Status bar     
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

xmlで設定してからactivityでthemeを設定することもできます
<style name="AppTheme" parent="AppBaseTheme">
    -- Status Bar -->
    <item name="android:windowTranslucentStatus">trueitem>
    -- Navigation Bar -->
    <item name="android:windowTranslucentNavigation">trueitem>
style>

半透明を設定した後、app全体が引き伸ばされることに注意してください.つまり、使用可能なレイアウト空間がスクリーン全体になります.すなわち、空間がstatus barによって遮断され、xmlでは、特定のコンポーネントが上部に移動しないようにコードを設定できます.私の提案は、もしあなたが元と同じようにしたいならば、直接レイアウトの最外層にlayoutを追加して、このlayoutの上でコードを使って、このように他のレイアウトはすべて元と一致して、遮る問題もありません.
android:fitsSystemWindows="true"

Androidの21以降には、ステータスバーの色を変更できるAPIが用意されています.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    getWindow().setStatusBarColor(Color.GREEN);
    getWindow().setNavigationBarColor(Color.GREEN);
    mText.setText(" ,        translucent bar   ,              ");
} else {
    mText.setText("  api  21  ");
}

Googleは開発者により良いapiを提供してappを開発していますが、これは私たちが勝手に操作したいほどではありません.そのため、より便利により一体化感のあるappを開発するために、System UI、すなわちStatus BarとNavigation Barを変更することは特に重要なステップです.ここでは、ツールクラスDyeingBarHelperについて、System UIをカスタマイズする方法を説明します.
げんり
 System UIとは、Decor View、すなわち1つのappのウィンドウWindowの最も基本的なコンポーネントview、すなわちRootViewを指し、DecorViewはFrameLayoutであり、そのサブviewはLinearLayoutの階層のみを含み、Linearlaoyout->FrameLaoyout->Linearlayoutの後は開発者がappインタフェースのレイアウト位置を追加することができます.SystemUIの実現はLinearlayout層にあるため、現在提供されているAPIはSystemUIを半透明に設定することができます.それでは、FrameLayoutで予め設定されたviewをSystemUIの位置に詰めることです.これで私たちは好きなようにviewを注文することができます.
DyeingBarHelperの使用
//             ,        
DyeingBarHelper.setBarTranslucent(this);
// DyeingBarHelper    
DyeingBarHelper helper = new DyeingBarHelper(this);
//      navigation bar status bar
// DyeingBarHelper helper = new DyeingBarHelper(this, statusView, navigationView);

//     
helper.setStatusBarColor(Color.BLUE);
helper.setNavigationBarColor(Color.BLUE);
//      
helper.setStatusBarViewAlpha(0);
helper.setNavigationBarViewAlpha(0);
//     
helper.setStatusBarViewVisibility(View.VISIBLE);
helper.setNavigationBarViewVisibility(View.VISIBLE);
//     
helper.setStatusBarViewBackground(drawable);
helper.setNavigationBarViewBackground(drawable);


DyeingBarHelperの実装
工事は主に3つの種類を含んで、1.DyeingBarHelper.JAvaの役割:SystemUIを設定します.2. SystemBarConfig.JAvaの役割:StatusBarの高さなど、System UIの設定を取得する.TintingUtil.JAvaの役割:染色を支援し、1つのviewから最も多い色、平均色などの背景色を取得します.便利な点は、title barから色を取得し、app全体の色を一体化させることができ、demoのslideviewのテストを見ることができます.
以下は主にDyeingBarHelperの全体的な考え方を紹介する:1.System UIの透過性が設定されているかどうかを判断します.これはflagによる演算とWindowのflagによる演算が可能である.フラグビットが設定されているかどうかを確認します.この方法はapi 19以降にのみ適用され,前述した.透明度を設定するには、前述したようにします.
//         api 19   
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    //      theme     bar   
    int[] attrs = new int[]{android.R.attr.windowTranslucentStatus,
            android.R.attr.windowTranslucentStatus};
    TypedArray typedArray = mContext.obtainStyledAttributes(attrs);
    try {
        isStatusBarTranslucent = typedArray.getBoolean(0, false);
        isStatusBarTranslucent = typedArray.getBoolean(1, false);
    } finally {
        typedArray.recycle();
    }

    //            bar  
    Window window = ((Activity) mContext).getWindow();
    WindowManager.LayoutParams layoutParams = window.getAttributes();
    int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
    if ((bits & layoutParams.flags) != 0) {
        isStatusBarTranslucent = true;
    }
    bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
    if ((bits & layoutParams.flags) != 0) {
        isNavigationBarTranslucent = true;
    }
}

2.すべての机械にNavigation Barがあるわけではないので、NavigationBarがあるかどうかを判断するには、この方法は本当にandroidの中のソースコードを勉强して、androidのソースコードを见ることをマスターしてこそ、ステップアップすることができます.
/**
 *  Android l       NavigationBar   ,    phoneWindowManager          
 *
 * @return
 */
public boolean hasNavigationBar() {
    boolean hasNavigationBar = false;
    Resources rs = mContext.getResources();
    int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
    if (id > 0) {
        hasNavigationBar = rs.getBoolean(id);
    }
    try {
        Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
        Method m = systemPropertiesClass.getMethod("get", String.class);
        String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
        if ("1".equals(navBarOverride)) {
            hasNavigationBar = false;
        } else if ("0".equals(navBarOverride)) {
            hasNavigationBar = true;
        }
    } catch (Exception e) {
        Log.w(TAG, e);
    }

    return hasNavigationBar;
}

3.status barとnavigation barがあればカスタムviewをそれらの位置に詰めることができ、得られたdecor viewはframe layoutであるため、layoutparamsはframe layoutを使用し、横画面と縦画面に注意し、携帯電話の現在の方向を判断する.また、status barの高さとnavigation barの高さをどのように得るかは、主にresource.getIdentifier()メソッドの取得は、もちろん、まず対応するフィールドを知る必要があります.
//          
this.isPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);

/**
 *   Status Bar   
 */
public int getStatusBarHeight() {
    String key = "status_bar_height";
    return getInternalDimensionSize(key);
}

/**
 *   Navigation Bar   
 *
 * @return
 */
public int getNavigationBarHeight() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        if (hasNavigationBar()) {
            String key;
            if (isPortrait) {
                key = "navigation_bar_height";
            } else {
                key = "navigation_bar_height_landscape";
            }
            return getInternalDimensionSize(key);
        }
    }
    return 0;
}

/**
 *   Navigation Bar   
 *
 * @return
 */
public int getNavigationBarWidth() {
    String key = "navigation_bar_width";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        if (hasNavigationBar()) {
            return getInternalDimensionSize(key);
        }
    }
    return 0;
}

/**
 *         
 *
 * @param key
 * @return
 */
private int getInternalDimensionSize(String key) {
    int result = 0;
    int resourceId = res.getIdentifier(key, "dimen", "android");
    if (resourceId > 0) {
        result = res.getDimensionPixelSize(resourceId);
    }
    return result;
}

/**
 *     Status Bar view
 *
 * @param decorViewGroup
 */
private void setStatusBarView(ViewGroup decorViewGroup) {
    if (mStatusBarView == null) {
        mStatusBarView = new View(mContext);
    }
    FrameLayout.LayoutParams params;
    params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
            mConfig.getStatusBarHeight());
    params.gravity = Gravity.TOP;
    //      ,       navigation bar   ,    navigation bar
    if (!mConfig.isNavigationBarAtBottom()) {
        params.rightMargin = mConfig.getNavigationBarWidth();
    }
    mStatusBarView.setLayoutParams(params);
    mStatusBarView.setBackgroundColor(DEFAULT_BAR_COLOR);
    decorViewGroup.addView(mStatusBarView);
}

/**
 *     Navigation Bar view
 *
 * @param decorViewGroup
 */
private void setNavigationBarView(ViewGroup decorViewGroup) {
    if (mNavigationBarView == null) {
        mNavigationBarView = new View(mContext);
    }
    FrameLayout.LayoutParams params;
    if (mConfig.isNavigationBarAtBottom()) {
        params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
        params.gravity = Gravity.BOTTOM;
    } else {
        params = new FrameLayout.LayoutParams(mConfig.getNavigationBarWidth(), FrameLayout.LayoutParams.MATCH_PARENT);
        params.gravity = Gravity.RIGHT;
    }
    mNavigationBarView.setLayoutParams(params);
    mNavigationBarView.setBackgroundColor(DEFAULT_BAR_COLOR);
    decorViewGroup.addView(mNavigationBarView);
}

これで大功を成し遂げた.
次にTintingUtilについて紹介します.この主な役割はviewの色を抽出することです.考え方は簡単です.viewのbitmapを取り出すことで、画素点ごとの色を得ることができます.そうすれば、類似色が最も多く求められ、平均色の求めができます.1.まずviewからbitmapを取得し、create bitmapの場合、メモリ不足を防止して複数回createを行うことが多い.
/**
 *  view      bitmap
 * @param view
 * @return
 */
protected Bitmap createBitmapFromView(View view) {
    // ImageView      drawable
    if (view instanceof ImageView) {
        Drawable drawable = ((ImageView) view).getDrawable();
        if (drawable != null && drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }
    }

    //     0,    activity  onCreate ,        
    int width = view.getWidth();
    int height = view.getHeight();

    Bitmap bitmap = createBitmapSafely(width, height, Bitmap.Config.ARGB_8888, 1);
    if (bitmap != null) {
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        canvas.setBitmap(null);
        canvas = null;
    }
    return bitmap;
}

/**
 *
 * @param width
 * @param height
 * @param config
 * @param times  create bitmap   ,        
 * @return
 */
protected Bitmap createBitmapSafely(int width, int height, Bitmap.Config config, int times) {
    try {
        return Bitmap.createBitmap(width, height, config);
    } catch (OutOfMemoryError e) {
        if (times > 0) {
            System.gc();
            return createBitmapSafely(width, height, config, --times);
        }
    } catch (Exception e) {
        Log.e(TAG, "view width or height shuold not < 0");
    }
    return null;
}

2.bitmapピクセルポイントの色を取得し、他の操作を行います.
int color = bitmap.getPixel(i, j);

DyeingBarHelperプロジェクト倉庫アドレス
参考サイト
android粒子爆発効果android systembartent
ちんせきじょうたいらん
このモードは主に1つのapp全体をスクリーン全体を占領することができ、ユーザーを完全にこのappに浸らせることができ、多くのappにはこのような機能があり、例えば読書類app、以下の展示図は小米が持っている読書appである.
げんり
主な原理はstatus barとnavigation barを隠すことです
実装(android公式サイト参照)
Androidの公式サイトにはこのようなSystem UIのチュートリアルがありますが、もっと詳しく知りたいなら公式サイトを参照することをお勧めします.
システムUIを操作する方法は、システムUIがactivityベースインタフェースdecor viewの1つのレイアウトに属するため、表示を設定することで表示と表示を実現できます.
//      decor view
mDecorView = getWindow().getDecorView();

/**
 *   status bar navigation bar
 */
private void hideSystemUI() {
    mDecorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE);
}

/** 
 *   status bar navigation bar
 */
private void showSystemUI() {
  mDecorView.setSystemUiVisibility(
          View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                  | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                  | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

System UIを非表示にした後、appの効果を読んだり、System UIをクリックしたりして、出現後に自動的に非表示にする方法を動的に制御します.これは、decorViewのListenerを設定し、SystemUIの変更をリスニングしながら、遅延タスクで操作できます.
mDecorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
            invokeHide();
        }
    }
});

public void invokeHide() {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            hideSystemUI();
        }
    }, 1000);
}

効果:
プロジェクトアドレス