It is believed that many of the first-line developers have encountered split lines, one of the most common elements of visual design, although simple and easy to draw, but in layout and typesetting often affect the view hierarchy of the important role. Often due to a small split line, not only in the layout of a number of views, but also easy to cause the layout level of deepening, and even need to do logic control in Java code.
While the Android-provided layout, such as the ListView, LinearLayout, and so on have a corresponding implementation of the split line, but in the processing of the separation line white this design often powerless. In more and more apps, the separation line has become a trend of design, so how to implement the split line simply and efficiently becomes a proposition worthy of study.
1, the ListView split Line
First of all, the ListView is the attribute with the split line (and the GridView does not, do not know what Android officials think), a total of four related attributes,divider,dividerheight, Headerdividersenabled,footerdividersenabled. Support to define the color and height of the split line, very useful properties, but in the actual development of designers do not like to follow the common sense of the card.
For example, the following list types of design drawings, designers like this left white right side of the banner or white on both sides of the design method.
The official division line is the left and right banner, developers encounter this problem, there are probably three kinds of conventional solutions.
Scenario 1:listview setting left and right margin or padding
Although this method can achieve the effect of dividing line left white, but there are certain limitations, the left side of the split line is not always designed to align with the content. At the same time, the defect is obvious, to the ListView set the left and right margin or padding, will cause the item click on the pressed background is also left white (effect). Of course, if you don't care about the details, it's understandable.
Defect: The effect of the press is defective, and if the split line is not aligned with the content, this method is not valid
Scenario 2: Set the background for each item with the split line left White
This is one of the more commonly used schemes, the dividing line normal display, the pressure effect is normal display. It seems perfect, but has to face a bigger problem, because the last item does not show the split line, so it needs to be controlled in Java code, such as this:
@Override publicgetView(int position, View convertView, ViewGroup parent) { .... if1) { convertView.setBackground(null); else { convertView.setBackgroundResource(R.drawable.bg_line); } return convertView; }
Controlling the view style in Java code is a pretty unreasonable choice anyway.
Second, this method does not support the footer and header of the split line, footerdividersenabled and headerdividersenabled two properties can not be used.
Then, since the use of a picture with a split line background, then, if the page design changes, parameter adjustment, you need to re-cut the diagram, so maintenance is quite laborious.
Finally, to set the background for the entire item view for a split line, you can basically assume that there is an over-drawn situation.
BUG: Code control view, footerdividersenabled and headerdividersenabled useless, white distance difficult to maintain, over-drawn
Scenario 3: Add a view in item to set the height background as the split line
<View android:layout_width="match_parent" android:layout_height="0.5dip" android:layout_marginLeft="15dip" android:background="#99cccccc"/>
This is the most common but most unreasonable plan, but many people do not realize unreasonable. In the above illustration, there is only one textview in item, so there is only one view of TextView in layout, but in this way, the layout must be linearlayout on the outer sleeve, so that the view level deepens and the view is redundant. Assuming a list shows 10 items, the number of redundant layouts is 20 (split line + + parent layout 10).
In addition, you can still avoid controlling the last display in Java, such as this:
View line = convertView.findViewById(R.id.item_line);1) { line.setVisibility(View.INVISIBLE);} else { line.setVisibility(View.VISIBLE);}
Footerdividersenabled and headerdividersenabled Two properties are also not available.
BUG: Layout Redundancy, Code control view, footerdividersenabled, and headerdividersenabled useless
Scenario 4: Redefining the bounds of the split line drawable
First of all, it is necessary to clear the fact that the contradiction point of the above situation is that the official ListView attribute does not support left and right white. So the best solution is to allow the official split line to support this functionality, which is both scalable and performance-enhancing.
First, a simple look at the ListView source code is how to achieve the function of the split line.
voidint childIndex) { // This widget draws the same divider for all children final Drawable divider = mDivider; divider.setBounds(bounds); divider.draw(canvas); }
In the OnDraw method, the Drawdivider method is eventually called. Since the split line is a Drawable object, the upper and lower left and right positions are controlled by the Rect object, which is set by the SetBounds method.
The top and bottom properties of this Rect object we don't need to care about, just look at the left and right two properties, left=paddingleft,right=width-paddingleft-paddingright by default, That means the start and end points of the split line run through the left and right sides of the ListView.
This can be verified in the Dispatchdraw method:
protected void dispatchDraw(Canvas canvas) { ... if (drawDividers || drawOverscrollHeader || drawOverscrollFooter) { final Rect bounds = mTempRect; bounds.left = mPaddingLeft; bounds.right = mRight - mLeft - mPaddingRight; ... drawDivider(canvas, bounds, i); } ... }
If we can modify the value of the left and right properties of the bounds, then we can control the margin of the split line.
Since you need to extend the ListView, the most common approach is to inherit the rewrite. Unfortunately, the access control of the Drawdivider method cannot be replicated, but thankfully the divider object of the ListView has setter and Getter methods.
The specific implementation logic is very simple, the core is the decoration mode , I will not go into detail.
Source code and examples see: https://github.com/MegatronKing/DividerSample
The usage is very simple, extending two properties to the ListView divider:dividerpaddingleft and dividerpaddingright, as the name implies. Both of these property values can be configured in the XML layout or in code.
The layout example is as follows:
<com .megatronking .divider .view xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:divider= "Http://schemas.android.com/apk/res-auto" android:id=< Span class= "hljs-string" > "@+id/list" android:layout_width= "match_parent" Android:layout_height= "wrap_content" android:divider= "#99cccccc" android:dividerheight= "0.5dip" Divider:dividerpaddingleft= "15dip" divider:dividerpaddingright=" 15dip "/>
Scenario 5: Defining drawable with inset tags
There is a special presence in the Drawable family:insetdrawable, can define the upper and lower left and right four boundaries of the white, insetdrawable also used the decorative mode, and the mechanism of Scheme 4 has the same wonderful. Redefine bound when the bound value of the decorated drawable changes. In addition, the most powerful is the ability to directly use XML definitions.
<inset xmlns:android = "http://schemas.android.com/ Apk/res/android " android:insetleft =" 15dip " ; <shape ; <size android:height =" 0.5dip "/> <solid android:color = "#99cccccc" /> </shape ; </ inset ;
The Insetleft, Insetright, Insettop, insetright Four properties allow you to define the size of the white space in different directions, plus support for Android: Drawable is familiar with referencing another drawable that is decorated drawable.
2, LinearLayout of the split line
LinearLayout added the split line properties starting with the Android 3.0 version. LinearLayout's split-line function is more powerful than the ListView, and is well supported in both horizontal and vertical linear layouts. To be compatible with the following versions of 3.0, a Linearlayoutcompat layout is provided in the V7 package, similar in usage.
However, there are not many developers who know about these properties, and many times they use a single view of the line. This approach undoubtedly uses cumbersome, layout redundancy.
Now let's briefly introduce the split line function of LinearLayout.
LinearLayout provides three split-line related properties:
1, Divider must refer to a drawable, cannot use or reference color. Drawable is generally defined as shape, which specifies a color by specifying a width or height with a size. In addition, because linearlayout is divided into horizontal and vertical layouts, two types of split lines are generally defined.
<shape xmlns:android = "http://schemas.android.com/ Apk/res/android "; <size android:height =" 0.5dip "/> <solid android:color = "#99cccccc" /> </ shape ;
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <size android:width="0.5dip"/> <solid android:color="#99cccccc"/></shape>
2, dividerpadding control the separation line of the left white distance, compared to the ListView split line banner, this property is very practical. But there is a flaw: dividerpadding can not specify around or up and down, horizontal layout in the upper and lower will be left white, vertical layout, left and right will have left white. And, designers often prefer to leave white on the right side of the banner, so this property is sometimes very awkward.
3, Showdividers This property is to control the location of the split line display, a total of four values: Middle Add a split line between each item; end adds a split line to the last item in the whole; Beginning adds a split line at the top of the whole; none If you do not set the value of this property, the default is None, that is, the split line is not displayed.
Although the linearlayout of the split line is very powerful, but encountered on one side of the situation, still helpless. Developers still have to go back to using view as a dividing line, such as the QQ browser layout:
Split line left white and text alignment, right banner, dividerpadding this property is powerless!
Before analyzing the solution, let's take a simple look at the principle of dividing line implementation!
void drawhorizontaldivider (Canvas canvas, int top) {mdivider.setbounds (getpaddin Gleft () + mdividerpadding, top , GETW Idth () -getpaddingright () -mdividerpadding, top + mdividerheight); Mdivider.draw (canvas ); }
drawVerticalDivider(Canvas canvas, int left) { mDivider.setBounds(leftgetPaddingTop() + mDividerPadding, leftgetHeight()getPaddingBottom() - mDividerPadding); mDivider.draw(canvas); }
A split line in a horizontal direction, and a split line in the vertical direction. The position of the split line is also determined by the SetBounds method, and the Mdividerpadding property is used for both left and right or up and down.
So, the solution should be exactly the same as the ListView mentioned earlier: redefine the bounds of the split line drawable
The source code does not elaborate, see: Https://github.com/MegatronKing/DividerSample
The extended LinearLayout provides an additional four properties for the split line: Dividerpaddingleft,dividerpaddingright,dividerpaddingtop,dividerpaddingbottom. Similarly, it can be configured in layout or dynamically in code.
When orientation is vertical, dividerpaddingleft and dividerpaddingright two attributes are in effect; orientation is horizontal, Dividerpaddingtop and Dividerpaddingbottom Two attributes are in effect.
The layout example is as follows:
<com.megatronking.divider.view.DividerLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:divider="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@drawable/line_horizontal" android:orientation="vertical" android:showDividers="middle" divider:dividerPaddingLeft="15dip"/>
Of course, through the insetdrawable way can also achieve the effect, the principle is almost, no longer repeat.
3. Summary
In general application development, the use of split line can reduce the number of views, hierarchy and code logic, but also facilitate the successor modification and maintenance. Although the performance is limited, but a little, for the pursuit of perfection and the ultimate developer, hope to be helpful!
This blog is not regularly updated continuously, welcome attention and Exchange:
Http://blog.csdn.net/megatronkings
Android Application Performance Optimization Series View--annoying split line left white solution