About Divider and AndroidDivider in Android

Source: Internet
Author: User

About Divider and AndroidDivider in Android

In Android Application Development, a divider is a split line between two views. I noticed this divider in my recent work and analyzed it. I found that there was something in it, and it was amazing...

Custom divider margins of ListView divider1.

By default, the divider of ListView is the right and right ends. How do I set a margin?

Using inset or layer-list can be implemented simply. The Code is as follows:

<! -- Method 1 --> <? Xml version = "1.0" encoding = "UTF-8"?> <Inset xmlns: android = "http://schemas.android.com/apk/res/android" android: insetLeft = "16dp"> <shape android: shape = "rectangle"> <solid android: color = "# f00"/> </shape> </inset> <! -- Method 2 --> <? Xml version = "1.0" encoding = "UTF-8"?> <Layer-list xmlns: android = "http://schemas.android.com/apk/res/android"> <item android: left = "16dp"> <shape android: shape = "rectangle"> <solid android: color = "# f00"/> </shape> </item> </layer-list>

Besides insetLeft, inset includes insetTop, insetRight, and insetBottom ,:

2. divider of the last item

Many people may find that the divider of the last ListView item sometimes exists and sometimes does not.

You can understand this by drawing a picture:

The above shows the effect of insufficient data. If the data is full, the last divider is not displayed.

The truth is that when the height of the ListView is not the last divider, the height of the ListView can be drawn only when match_parent is used.

Ps: The last divider and footerDividersEnabled are mixed in a lot of information on the Internet. This is incorrect. The two are logically independent. Similarly, there is a headerDividersEnabled, headerDividersEnabled and footerDividersEnabled do not affect the rendering of the last divider by default. They are dedicated to headers and footer.

Divider of RecyclerView

The Divider of RecyclerView is called ItemDecoration, and RecyclerView. ItemDecoration is an abstract class, which is not officially provided by default.

In the official Support7Demos example, there is a DividerItemDecoration. For more information, see here in the sdk:

Extras/android/support/samples/Support7Demos/src /... /... /Decorator/DividerItemDecoration. java

However, this DividerItemDecoration has three problems:

To address these problems, I fixed and enhanced the following:

Import android. content. context; import android. content. res. typedArray; import android. graphics. canvas; import android. graphics. rect; import android. graphics. drawable. drawable; import android. support. v4.view. viewCompat; import android. support. v7.widget. linearLayoutManager; import android. support. v7.widget. recyclerView; import android. view. view;/*** default Implementation of ItemDecoration of RecyclerView * 1. the system split line is used by default * 2. support Customization Type * 3. supports horizontal and vertical directions * 4. fixed the bug * expanded from DividerItemDecoration */public class DividerItemDecoration extends RecyclerView in Support7Demos of the official android sdk. itemDecoration {private static final int [] ATTRS = new int [] {android. r. attr. listDivider}; public static final int HORIZONTAL_LIST = LinearLayoutManager. HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager. VERTI CAL; private Drawable mDivider; private int mWidth; private int mHeight; private int mOrientation; public DividerItemDecoration (Context context, int orientation) {final TypedArray a = context. obtainStyledAttributes (ATTRS); mDivider =. getDrawable (0);. recycle (); setOrientation (orientation);}/*** added: Support for custom dividerDrawable ** @ param context * @ param orientation * @ param dividerDrawable */publi C producer (Context context, int orientation, Drawable dividerDrawable) {mDivider = dividerDrawable; setOrientation (orientation);} public void setOrientation (int orientation) {if (orientation! = HORIZONTAL_LIST & orientation! = VERTICAL_LIST) {throw new IllegalArgumentException ("invalid orientation");} mOrientation = orientation;}/*** added: manual setting of width * @ param width */public void setWidth (int width) {this. mWidth = width;}/*** added: supports manual setting of height for drawable without high width * @ param height */public void setHeight (int height) {this. mHeight = height;} @ Override public void onDraw (Canvas c, RecyclerView parent) {if (mOrienta Tion = VERTICAL_LIST) {drawVertical (c, parent);} else {drawHorizontal (c, parent) ;}} public void drawVertical (Canvas c, RecyclerView parent) {final int left = parent. getPaddingLeft (); final int right = parent. getWidth ()-parent. getPaddingRight (); final int childCount = parent. getChildCount (); for (int I = 0; I <childCount; I ++) {final View child = parent. getChildAt (I); final RecyclerView. LayoutParams params = (RecyclerView. layoutParams) child. getLayoutParams (); final int top = child. getBottom () + params. bottomMargin + Math. round (ViewCompat. getTranslationY (child); final int bottom = top + getDividerHeight (); mDivider. setBounds (left, top, right, bottom); mDivider. draw (c) ;}} public void drawHorizontal (Canvas c, RecyclerView parent) {final int top = parent. getPaddingTop (); final Int bottom = parent. getHeight ()-parent. getPaddingBottom (); final int childCount = parent. getChildCount (); for (int I = 0; I <childCount; I ++) {final View child = parent. getChildAt (I); final RecyclerView. layoutParams params = (RecyclerView. layoutParams) child. getLayoutParams (); final int left = child. getRight () + params. rightMargin + Math. round (ViewCompat. getTranslationX (child); final int rig Ht = left + getDividerWidth (); mDivider. setBounds (left, top, right, bottom); mDivider. draw (c) ;}@ Override public void getItemOffsets (Rect outRect, int itemPosition, RecyclerView parent) {if (mOrientation = VERTICAL_LIST) {outRect. set (0, 0, 0, getDividerHeight ();} else {outRect. set (0, 0, getDividerWidth (), 0) ;}} private int getDividerWidth () {return mWidth> 0? MWidth: mDivider. getIntrinsicWidth ();} private int getDividerHeight () {return mHeight> 0? MHeight: mDivider. getIntrinsicHeight ();}}

Use:

// DividerdividerItemDecoration = new DividerItemDecoration (this, DividerItemDecoration. VERTICAL_LIST); // dividerdividerItemDecoration = new DividerItemDecoration (this, DividerItemDecoration. VERTICAL_LIST, getResources (). getDrawable (R. drawable. ic_launcher); // custom divider-vertical list dividerItemDecoration = new DividerItemDecoration (this, DividerItemDecoration. VERTICAL_LIST, new ColorDrawable (Color. parseColor ("# ff00ff"); dividerItemDecoration. setHeight (1); // customize divider-Level list dividerItemDecoration = new DividerItemDecoration (this, DividerItemDecoration. HORIZONTAL_LIST, new ColorDrawable (Color. parseColor ("# ff00ff"); dividerItemDecoration. setWidth (1); // customize the divider with a margin and without a high width (the preceding InsetDrawable is used as an example) // you can set the size to specify the width and height in the xml file of drawable. dividerItemDecoration = new DividerItemDecoration (this, DividerItemDecoration. HORIZONTAL_LIST, getResources (). getDrawable (R. drawable. list_divider); dividerItemDecoration. setWidth (DisplayLess. $ dp2px (16) + 1 );
Manual Divider

Sometimes there is no native support for system controls. You can only manually add a divider to two views. For example, you can set the divider between each item on the interface, add a vertical divider between several views with an average horizontal score.

Whether it is horizontal or vertical, it is very simple. Set a View and set a background. Normally there is nothing to say.

Next we will consider a common setting interface. The split line of this setting interface has a left margin, such as the setting interface. I believe most people's layout code is implemented like this:

<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: layout_height = "match_parent"> <! -- The background of group_container must be set and consistent with list_item_normal of list_item_bg. Otherwise, the effect will be incorrect. --> <LinearLayout android: id = "@ + id/group_container" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignParentTop = "true" android: layout_marginTop = "48dp" android: background = "# fff" android: orientation = "vertical"> <RelativeLayout android: id = "@ + id/account_container" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: background = "@ drawable/list_item_bg" android: clickable = "true"> <TextView android: id = "@ + id/account_title" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignParentLeft = "true" android: layout_centerVertical = "true" android: layout_margin = "16dp" android: text = "First Item" android: textColor = "# f00" android: textSize = "16sp"/> </RelativeLayout> <View android: layout_width = "match_parent" android: layout_height = "1px" android: layout_marginLeft = "16dp" android: background = "# f00"/> <RelativeLayout android: id = "@ + id/phone_container" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: background = "@ drawable/list_item_bg" android: clickable = "true"> <TextView android: id = "@ + id/phone_title" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignParentLeft = "true" android: layout_centerVertical = "true" android: layout_margin = "16dp" android: text = "Second Item" android: textColor = "# f00" android: textSize = "16sp"/> </RelativeLayout> </LinearLayout> </RelativeLayout>

The following figure shows its Overdraw status:

By analyzing the Overdraw hierarchy, we found that the background of the entire groud_container was set for a small margin, resulting in an Overdraw.

Can I optimize this Overdraw? The answer is yes.

The background must be removed, but the left-side View cannot be written in this simple way. You need to customize a View, it must be able to draw the 16dp line from the left margin with the color value of list_item_normal so that the left margin can be viewed.

The specific code for this View is as follows:

import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import com.jayfeng.lesscode.core.R;public class SpaceDividerView extends View {    private int mSpaceLeft = 0;    private int mSpaceTop = 0;    private int mSpaceRight = 0;    private int mSpaceBottom = 0;    private int mSpaceColor = Color.TRANSPARENT;    private Paint mPaint = new Paint();    public SpaceDividerView(Context context) {        this(context, null);    }    public SpaceDividerView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public SpaceDividerView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpaceDividerView, defStyleAttr, 0);        mSpaceLeft = a.getDimensionPixelSize(R.styleable.SpaceDividerView_spaceLeft,                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));        mSpaceTop = a.getDimensionPixelSize(R.styleable.SpaceDividerView_spaceTop,                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));        mSpaceRight = a.getDimensionPixelSize(R.styleable.SpaceDividerView_spaceRight,                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));        mSpaceBottom = a.getDimensionPixelSize(R.styleable.SpaceDividerView_spaceBottom,                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));        mSpaceColor = a.getColor(R.styleable.SpaceDividerView_spaceColor, Color.TRANSPARENT);        a.recycle();        mPaint.setColor(mSpaceColor);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (mSpaceLeft > 0) {            canvas.drawRect(0, 0, mSpaceLeft, getMeasuredHeight(), mPaint);        }        if (mSpaceTop > 0) {            canvas.drawRect(0, 0, getMeasuredWidth(), mSpaceTop, mPaint);        }        if (mSpaceRight > 0) {            canvas.drawRect(getMeasuredWidth() - mSpaceRight, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);        }        if (mSpaceBottom > 0) {            canvas.drawRect(0, getMeasuredHeight() - mSpaceBottom, getMeasuredWidth(), getMeasuredHeight(), mPaint);        }    }}

With this SpaceDividerView, we can rewrite the layout code above:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto">    <LinearLayout android:id="@+id/group_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="48dp" android:orientation="vertical">        <RelativeLayout android:id="@+id/account_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_item_bg" android:clickable="true">            <TextView android:id="@+id/account_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_margin="16dp" android:text="First Item" android:textColor="#f00" android:textSize="16sp" />        </RelativeLayout>        <com.jayfeng.lesscode.core.other.SpaceDividerView android:layout_width="match_parent" android:layout_height="1px" android:background="#f00" app:spaceLeft="16dp" app:spaceColor="@color/list_item_normal"/>        <RelativeLayout android:id="@+id/phone_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_item_bg" android:clickable="true">            <TextView android:id="@+id/phone_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_margin="16dp" android:text="Second Item" android:textColor="#f00" android:textSize="16sp" />        </RelativeLayout>    </LinearLayout></RelativeLayout>

And Overdraw status are as follows:

The group_container block in the interface is changed from green to blue, which means that the Overdraw is reduced once.

In the above cases, SpaceDividerView decouples the background color and optimizes Overdraw. This SpaceDividerView also supports four directions, which is especially convenient to use.

Shadow divider

The Shadow split line overlaps the following view to achieve a three-dimensional effect of the split line.

You can use RelativeLayout to control the distance above:

<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent" android: layout_height = "match_parent"> <! -- The value of layout_marginTop should be the header height excluding the shadow height --> <LinearLayout android: layout_width = "match_parent" android: layout_height = "match_parent" android: layout_alignParentTop = "true: layout_marginTop = "@ dimen/header_height" android: orientation = "vertical"> </LinearLayout> <! -- This must be placed at the end of the header to be displayed at the top. This header contains a shadow View --> <include android: id = "@ + id/header" layout = "@ layout/include_header"/> </RelativeLayout>

Although it's a little simpler, let's analyze it a little bit. If the header includes the content 48dp and the shadow 8dp, then the marginTop is 48dp.

Q: customized IT education platform, one-to-one service, Q & A. Official Website for developing programming social headlines: www.wenaaa.com

QQ Group 290551701 has gathered many Internet elites, Technical Directors, architects, and project managers! Open-source technology research, welcome to the industry, Daniel and beginners interested in IT industry personnel!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.