Android Open Source - android-extendedactionbar Extended Action Bar Activity






From Project

Back to project page android-extendedactionbar.

License

The source code is released under:

MIT License

If you think the Android project android-extendedactionbar listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package me.eugeniomarletti.extendedactionbar;
//  www  .j ava2 s.com
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.FrameLayout;

/**
 * Example {@code Activity} to show how to automatically eliminate overdraw caused by the window background.
 * <p/>
 * If {@link Build.VERSION#SDK_INT} is >= 19, automatically extracts the required drawables from the window background
 * which must be a {@link android.graphics.drawable.LayerDrawable} with at least 2 children with the following
 * {@code android:id}:
 * <ul>
 * <li>{@link R.id#statusbar_background}</li>
 * <li>{@link R.id#window_background}</li>
 * </ul>
 * </p>
 */
public class ExtendedActionBarActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        final Resources res = getResources();
        final boolean isKitkat = Build.VERSION.SDK_INT >= 19;

        // replace window background to reduce overdraw
        final Window window = getWindow();
        final ViewGroup contentView = (ViewGroup)findViewById(android.R.id.content);
        final View content = contentView.getChildAt(0);
        final Drawable extendedWindowBackground = window.getDecorView().getBackground();
        final Drawable windowBackground = !isKitkat ? extendedWindowBackground
                                                    : getWindowBackgroundLayer(extendedWindowBackground,
                                                                               R.id.window_background,
                                                                               "window_background");
        window.setBackgroundDrawable(null);
        setBackground(content, windowBackground);

        // add statusbar background
        if (isKitkat)
        {
            // check if translucent bars are enabled
            final int config_enableTranslucentDecor_id =
                    res.getIdentifier("config_enableTranslucentDecor", "bool", "android");
            if (config_enableTranslucentDecor_id > 0 && res.getBoolean(config_enableTranslucentDecor_id))
            {
                // get ActionBar container
                final View actionBarContainer = findViewById("action_bar_container", "android");
                if (actionBarContainer != null)
                {
                    // add layout listener (can't get margin before layout)
                    //noinspection ConstantConditions
                    actionBarContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver
                            .OnGlobalLayoutListener()
                    {
                        @SuppressWarnings("ConstantConditions")
                        @Override
                        public void onGlobalLayout()
                        {
                            // remove layout listener
                            final ViewTreeObserver vto = actionBarContainer.getViewTreeObserver();
                            if (Build.VERSION.SDK_INT < 16)
                                vto.removeGlobalOnLayoutListener(this);
                            else vto.removeOnGlobalLayoutListener(this);

                            // create and add statusbar background view
                            final Drawable statusBarBackground = getWindowBackgroundLayer(extendedWindowBackground,
                                                                                          R.id.statusbar_background,
                                                                                          "statusbar_background");
                            final int statusBarHeight =
                                    ((ViewGroup.MarginLayoutParams)actionBarContainer.getLayoutParams()).topMargin;
                            final View statusBarView = new View(ExtendedActionBarActivity.this);
                            setBackground(statusBarView, statusBarBackground);
                            final FrameLayout.LayoutParams statusBarBackground_lp = new FrameLayout.LayoutParams(
                                    ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight,
                                    Gravity.TOP | Gravity.FILL_HORIZONTAL);
                            contentView.addView(statusBarView, 0, statusBarBackground_lp);

                            // shift content under actionbar
                            final ViewGroup.MarginLayoutParams content_lp =
                                    (ViewGroup.MarginLayoutParams)content.getLayoutParams();
                            content_lp.topMargin = getActionBar().getHeight() + statusBarHeight;
                            content.setLayoutParams(content_lp);
                        }
                    });
                }
            }
        }
    }

    /**
     * Find a view by providing the id resource name and package in the form {@code @package/id:name}.
     * <p>
     * Useful for getting "private" views like {@code @android:id/action_bar_container}.
     * </p>
     *
     * @param name the resource id name (for example @android.id:resource would be "resource").
     * @param pkg  the resource package (for example @android.id:resource would be "android").
     *
     * @return The view if found and data is valid, or {@code null}.
     */
    public View findViewById(String name, String pkg)
    {
        final int id = getResources().getIdentifier(name, "id", pkg);
        return id > 0 ? findViewById(id) : null;
    }

    /**
     * Uses {@link android.view.View#setBackground(android.graphics.drawable.Drawable)}
     * if SDK >= 16, else falls back on
     * {@link android.view.View#setBackgroundDrawable(android.graphics.drawable.Drawable)}.
     *
     * @param background the {@code Drawable} to use as the background, or null to remove the background.
     */
    private static void setBackground(View view, Drawable background)
    {
        if (Build.VERSION.SDK_INT < 16) view.setBackgroundDrawable(background);
        else view.setBackground(background);
    }

    /**
     * Extracts the requested layer from the window drawable or throws an {@link java.lang.IllegalAccessException} if
     * the window drawable is not a {@link android.graphics.drawable.LayerDrawable} or the requested layer is missing.
     *
     * @param windowBackground the window background.
     * @param layerId          the layer id like {@code R.id.statusbar_background}.
     * @param layerIdName      the layer id name like "statusbar_background".
     *
     * @return The requested layer.
     */
    private static Drawable getWindowBackgroundLayer(Drawable windowBackground, int layerId, String layerIdName)
    {
        if (!(windowBackground instanceof LayerDrawable))
            throw new IllegalStateException("Window background must be a LayerDrawable.");
        final Drawable layer = ((LayerDrawable)windowBackground).findDrawableByLayerId(layerId);
        if (layer == null) throw new IllegalStateException(
                String.format("Window background must have layer with android:id=\"@+id/%s\"", layerIdName));
        return layer;
    }
}




Java Source Code List

me.eugeniomarletti.extendedactionbar.ExtendedActionBarActivity.java