Implementation of the stream layout of popular tags in Android, android tag Layout

Source: Internet
Author: User

Implementation of the stream layout of popular tags in Android, android tag Layout

I. Overview:
In daily app usage, we will see popular labels and other auto-wrapping stream la s in android apps. Today, let's take a look at how

Customize a stream layout similar to popular labels (the source code is downloaded at the end of the article below)

Similar custom layout. Next we will introduce in detail the application characteristics of stream layout and the technical points used:

1. Streaming Layout features and application scenarios
Feature: when the space of the above row is insufficient to accommodate the new TextView,
To open up space for the next row.

Schematic:

  

Scenario: Mainly used for keyword search or popular tags
2. Customize ViewGroup. Rewrite the following two methods.

1. onMeasure: measure the width and height of the sub-view and set the width and height of the sub-view.

2. onLayout: Set the position of the subview.

OnMeasure: sets the Measurement Mode and measurement value for the Child view based on the attributes in the layout file of the Child view.
Measurement = Measurement Mode + measurement value;

There are three measurement modes:
EXACTLY: Specifies the exact value. Generally, when childView sets its width and height to the exact value or match_parent, ViewGroup sets it to EXACTLY;
AT_MOST: indicates that the sub-layout is limited to a maximum value. Generally, when the width and height of childView are set to wrap_content, ViewGroup sets it to AT_MOST;
UNSPECIFIED: indicates the size of the sub-layout. It usually appears in the heightMode of the item in AadapterView and in the childView of ScrollView. This mode is rare.
3. LayoutParams
ViewGroup LayoutParams: Each ViewGroup corresponds to one LayoutParams, that is, ViewGroup-> LayoutParams
GetLayoutParams:
The LayoutParams obtained by the sub-View. getLayoutParams corresponds to the LayoutParams of the parent control of the sub-View;
For example, the subview. getLayoutParams-> LinearLayout. LayoutParams in LinearLayout
Therefore, we also need a LayoutParams for FlowLayout, because the above is the sub-View's margin,
So we should use MarginLayoutParams. That is, FlowLayout-> MarginLayoutParams

4. Finally, let's take a look at the final implementation:


II. Implementation of stream layout of hot tags:

1. ViewGroup implementation for custom hot tags

According to the above technical analysis, the custom class inherits from ViewGroup and overwrites methods such as onMeasure and onLayout. The specific implementation code is as follows:

Package com. czm. flowlayout; import java. util. arrayList; import java. util. list; import android. content. context; import android. util. attributeSet; import android. view. view; import android. view. viewGroup; /***** @ author caizhiming * @ created on 2015-4-13 */public class XCFlowLayout extends ViewGroup {// store all sub-View private lists <List <View> mAllChildViews = new ArrayList <> (); // The height of each row is private List <Integer> mLin EHeight = new ArrayList <> (); public XCFlowLayout (Context context) {this (context, null); // TODO Auto-generated constructor stub} public XCFlowLayout (Context context, attributeSet attrs) {this (context, attrs, 0); // TODO Auto-generated constructor stub} public XCFlowLayout (Context context, AttributeSet attrs, int defStyle) {super (context, 0, attrs, defStyle); // TODO Auto-generated constructor st Ub} @ Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stub // the width and height passed in by the parent control and the corresponding measurement mode int sizeWidth = MeasureSpec. getSize (widthMeasureSpec); int modeWidth = MeasureSpec. getMode (widthMeasureSpec); int sizeHeight = MeasureSpec. getSize (heightMeasureSpec); int modeHeight = MeasureSpec. getMode (heightMeasureSpec); // If the width and height of the current ViewGroup are wrap_conten T case int width = 0; // self-measured width int height = 0; // self-measured height // records the width and height of each row int lineWidth = 0; int lineHeight = 0; // obtain the number of subviews int childCount = getChildCount (); for (int I = 0; I <childCount; I ++) {View child = getChildAt (I); // measure the width and height of the subview measureChild (child, widthMeasureSpec, heightMeasureSpec); // obtain the LayoutParams MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams (); // The width occupied by the sub-View, int childWidth = Child. getMeasuredWidth () + lp. leftMargin + lp. rightMargin; // The height occupied by the sub-View: int childHeight = child. getMeasuredHeight () + lp. topMargin + lp. bottomMargin; // if (lineWidth + childWidth> sizeWidth) during line feed {// obtain the maximum width of width = Math. max (width, lineWidth); // reset lineWidth = childWidth; // record Row height + = lineHeight; lineHeight = childHeight ;} else {// No line feed // overlay the line width lineWidth + = childWidth; // get the line with the largest line Height = Math. max (lineHeight, childHeight);} // process the last child View if (I = childCount-1) {width = Math. max (width, lineWidth); height + = lineHeight; }}// wrap_content setMeasuredDimension (modeWidth = MeasureSpec. EXACTLY? SizeWidth: width, modeHeight = MeasureSpec. EXACTLY? SizeHeight: height); super. onMeasure (widthMeasureSpec, heightMeasureSpec);} @ Override protected void onLayout (boolean changed, int l, int t, int r, int B) {// TODO Auto-generated method stub mAllChildViews. clear (); mLineHeight. clear (); // obtain the width of the current ViewGroup, int width = getWidth (); int lineWidth = 0; int lineHeight = 0; // record the view List of the current row <View> lineViews = new ArrayList <View> (); int childCount = getChildCount (); for (int I = 0; I <childCount; I ++) {View child = getChildAt (I); MarginLayoutParams lp = (MarginLayoutParams) child. getLayoutParams (); int childWidth = child. getMeasuredWidth (); int childHeight = child. getMeasuredHeight (); // if you need to wrap the line if (childWidth + lineWidth + lp. leftMargin + lp. rightMargin> width) {// record LineHeight mLineHeight. add (lineHeight); // record the Views mAllChildViews of the current row. add (lineViews); // reset the line width and height lineWidth = 0; lineHeight = childHeight + lp. topMargin + lp. bottomMargin; // resets the lineViews of a view set = new ArrayList ();} lineWidth + = childWidth + lp. leftMargin + lp. rightMargin; lineHeight = Math. max (lineHeight, childHeight + lp. topMargin + lp. bottomMargin); lineViews. add (child);} // process the last line of mLineHeight. add (lineHeight); mAllChildViews. add (lineViews); // set the position of the sub-View to int left = 0; int top = 0; // get the number of rows int lineCount = mAllChildViews. size (); for (int I = 0; I <lineCount; I ++) {// views and height of the current row lineViews = mAllChildViews. get (I); lineHeight = mLineHeight. get (I); for (int j = 0; j <lineViews. size (); j ++) {View child = lineViews. get (j); // determines whether to display if (child. getVisibility () = View. GONE) {continue;} MarginLayoutParams lp = (MarginLayoutParams) child. getLayoutParams (); int cLeft = left + lp. leftMargin; int cTop = top + lp. topMargin; int cRight = cLeft + child. getMeasuredWidth (); int cBottom = cTop + child. getMeasuredHeight (); // child View layout child. layout (cLeft, cTop, cRight, cBottom); left + = child. getMeasuredWidth () + lp. leftMargin + lp. rightMargin;} left = 0; top + = lineHeight;}/*** LayoutParams corresponding to the current ViewGroup */@ Override public LayoutParams generateLayoutParams (AttributeSet attrs) {// TODO Auto-generated method stub return new MarginLayoutParams (getContext (), attrs );}}

2. Related layout files:

Reference custom controls:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/container"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.czm.flowlayout.XCFlowLayout        android:id="@+id/flowlayout"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </com.czm.flowlayout.XCFlowLayout></RelativeLayout>

TextView style file:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >    <solid android:color="#666666" />    <corners android:radius="10dp" />    <padding         android:left="5dp"        android:right="5dp"        android:top="5dp"        android:bottom="5dp"         /></shape>

3. Use the custom Layout control class

Finally, how can I use the custom popular tag control class? It is very simple. Please refer to the following instance code:

package com.czm.flowlayout;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.view.ViewGroup.LayoutParams;import android.view.ViewGroup.MarginLayoutParams;import android.widget.TextView;/** *  * @author caizhiming * @created on 2015-4-13 */public class MainActivity extends Activity {    private String mNames[] = {            "welcome","android","TextView",            "apple","jamy","kobe bryant",            "jordan","layout","viewgroup",            "margin","padding","text",            "name","type","search","logcat"    };    private XCFlowLayout mFlowLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                initChildViews();            }    private void initChildViews() {        // TODO Auto-generated method stub        mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout);        MarginLayoutParams lp = new MarginLayoutParams(                LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);        lp.leftMargin = 5;        lp.rightMargin = 5;        lp.topMargin = 5;        lp.bottomMargin = 5;        for(int i = 0; i < mNames.length; i ++){            TextView view = new TextView(this);            view.setText(mNames[i]);            view.setTextColor(Color.WHITE);            view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));            mFlowLayout.addView(view,lp);        }    }}

4. Download source code

Finally give the source code download: http://download.csdn.net/detail/jczmdeveloper/8590113

After downloading the source code, we often ignore the main point, that is, the security of the source code. Here, you can click Android encryption, Which is encrypted by mobile application security intelligent service provider, to protect the source code!

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.