Add elevation/shadow on toolbar for pre-lollipop devices

前端 未结 8 1269
猫巷女王i
猫巷女王i 2020-11-28 05:39

I updated my android app to the new material design, but I also wanted to add some shadow or elevation to the Toolbar. There seem to be some (hacky) ways of doing it via ima

8条回答
  •  借酒劲吻你
    2020-11-28 06:17

    I have also lost 1 day on this issue, but I finally figured out a way to make it work.

    /**
     * Controller for the toolbar which will take care of the drop down shadow also on pre-lollipop devices.
     * 
    * The controller also handles the status bar based on the state of the toolbar. *

    * Created by Negru Ionut Valentin on 20/1/2016. */ public class ToolbarController { private boolean handleStatusBar = false; private boolean showTitle = true; /** * Call this method in onCreate() method of your Activity or in onCreateView() in Fragment * * @param view * The view into which to look for the toolbar * @param activity * The activity for which setup the toolbar * * @return The toolbar found and customized or {@code null} */ public Toolbar initToolbar(View view, Activity activity) { Toolbar mToolbar = (Toolbar) view.findViewById(R.id.toolbar); // Valid and visible toolbar - otherwise ignore if (null != mToolbar && mToolbar.getVisibility() == View.VISIBLE) { int paddingLeft = mToolbar.getPaddingLeft(); int paddingRight = mToolbar.getPaddingRight(); int paddingBottom = mToolbar.getPaddingBottom(); // Set the top padding of the toolbar to match the status bar height int paddingTop = new CynnyContextWrapper(activity).getStatusBarHeight(); mToolbar.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { ViewParent parent = mToolbar.getParent(); if (parent instanceof RelativeLayout) { // Manually create the drop shadow RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Metrics.convertDpToPixel(4, activity)); View dropShadow = new View(activity); dropShadow.setBackgroundResource(R.drawable.toolbar_shadow); params.addRule(RelativeLayout.BELOW, R.id.toolbar); ((RelativeLayout) parent).addView(dropShadow, params); } } if (activity instanceof AppCompatActivity) { // Check if the Activity actually support ActionBar with Toolbar and set our custom Toolbar for it ((AppCompatActivity) activity).setSupportActionBar(mToolbar); // Get the actionbar from the activity ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar(); if (null != actionBar) { // If the actionbar is valid, customize it actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); actionBar.setDisplayShowTitleEnabled(this.showTitle); mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_selector); } } if (this.handleStatusBar) { // For showing the status bar activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); } } else if (handleStatusBar) { // Force hide the status bar activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); } return mToolbar; } /** * Set the flag indicating if the controller should handle or not the status bar. * * @param handleStatusBar * Flag which indicates if the initialization of the toolbar should also update * the status bar state (if two calls are made for the init, the last one will * be taken into consideration). * * @return The current toolbar controller. */ public ToolbarController setHandleStatusBar(boolean handleStatusBar) { this.handleStatusBar = handleStatusBar; return this; } /** * Set the flag indicating if the toolbar should show or hide the title. * * @param showTitle * Flag indicating if the toolbar should also show the title (the title can be changed after the toolbar * initialization) * * @return The current toolbar controller. */ public ToolbarController setShowTitle(boolean showTitle) { this.showTitle = showTitle; return this; } }

    In the activity you should use this in onCreate() method like this:

    // Create and customize the Toolbar controller
    new ToolbarController().setHandleStatusBar(true).setShowTitle(true)
                                     .initToolbar(((ViewGroup) findViewById(android.R.id.content)).getChildAt(0),
                                                  this);
    

    In the fragment you should use this in onCreateView() method like this:

    new ToolbarController().setHandleStatusBar(false).setShowTitle(false).initToolbar(resultView, getActivity());
    

    Do not forget to add you toolbar in the layouts and set it's id with android:id="@id/toolbar". If you want to use another id, you can customize the controller and add another setter method which uses the id you provide.

    I have two toolbar layouts created:

    v21

        
        
    
    

    other

    
    
    
        
        
    
    
    

    I use them in may layouts using:

    
    

    I hope this will help to solve your issue. Also take note this can be optimized further more, but it works for me and I don't want to loose anymore time on this issue.

提交回复
热议问题