Android development of long-distance foreign--custom view of various poses 2

Source: Internet
Author: User

This article is a series of articles, I am in the long-distance development of Android a little thoughts and records, I will try to follow the first easy after the difficult sequence to write the series. The series cited the "Android Development art exploration" and "in-depth understanding of Android volume Ⅰ,ⅱ,ⅲ" in the relevant knowledge, in addition to learn from other high-quality blog, here to the great God to thank you, worship!!! In addition, this article series of knowledge may require a certain Android Development Foundation and project experience to better understand, that is, the series of articles for Android Advanced Development engineer.

In the previous article, we analyzed the Android event system in detail. Also from the source point of view a thorough understanding of why this performance. Not only to know it, but also to know the reason why. So in this article, we still come from the definition view. Different from the previous one, the focus of this chapter is on the ViewGroup. We know that ViewGroup is a subclass of view, and there are many controls in the Android system that inherit from ViewGroup. For example, our common framelayout, LinearLayout, relativelayout and other layouts are inherited from the viewgroup. Custom ViewGroup is more difficult because ViewGroup wants to manage the measurement, layout, etc. of sub-view. About the measurement, layout, and mapping of the view, the Premeasure, Windowlayout, endmeasure, layout, and Viewrootimpl of the display of our long distance ⅴ--activity in Android development Draw has been analyzed in detail.

Note: I really dug a big hole for myself, about custom ViewGroup instance I thought for a long time also looked for a long time. Find that you want to implement a very standardized custom view is a certain price, this point you look at the linearlayout system itself, such as the ViewGroup control of the source code will know that their implementation is very complex. Want to choose a simpler to put, do not want to water, more difficult to put, feel and go around the code of the Dead end. Readers should not be able to have a clearer understanding of the core of a custom viewgroup. Until today, I really want to say sorry to everyone. Well, these "sentimental" words are not much to say, we still look at the following example.

Implementing streaming Layouts FlowLayout

I found an effect under the Web App search for a company or post

Pull Hook net These show the specific data how come we don't discuss, we try to achieve this layout effect.

At the top of the tag "guess you Like", "hot Company" can be shown with a textview, we ignore it. The key is the bottom label flow layout. We're going to analyze it.

    • First, the label in the flow layout should be a textview, and about the ellipse boundary underneath it, we can make a background

Layout/tag_view.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_margin="5dp"          android:background="@drawable/tag_bg"          android:text="Helloworld"          android:textSize="15sp"          android:textColor="@drawable/text_color"></TextView>

Drawable/tag_bg.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item        android:drawable="@drawable/checked_bg"        android:state_checked="true"        >    </item>    <item          android:drawable="@drawable/normal_bg"></item></selector>

Drawable/checked_bg.xml

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

Drawable/normal_bg.xml

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >    <solid android:color="#ffffff" />    <corners android:radius="30dp" />    <stroke android:color="#88888888"  android:width="1dp"/>    <padding        android:bottom="2dp"        android:left="10dp"        android:right="10dp"        android:top="2dp" /></shape>

Drawable/text_color.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:color="#888888"/></selector>

The top layout can be previewed as follows

So far, we have finished the preparation work.

    • Custom ViewGroup (emphasis)

Above we have got a layout file that achieves the appearance of sub-view in our streaming layout. Then we're going to come up with a definition of viewgroup to implement the flow layout described above.
① first inherits from ViewGroup, inherits from ViewGroup overrides its constructor and OnLayout method, we use the Androidstudio hint to be OK

public class MyTagFlowLayout extends ViewGroup {  public MyTagFlowLayout(Context context) {       this(context, null);   }   public MyTagFlowLayout(Context context, AttributeSet attrs) {       this(context, attrs,0);   }   public MyTagFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {       this(context, attrs,defStyleAttr,0);   }      @SuppressLint("NewApi")   public MyTagFlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {       super(context, attrs, defStyleAttr, defStyleRes); @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        }}

② initialization of some information

//由可知,我们可将上面的流式布局分为三部分//每一行的View 组成的List private List<View> lineViews = new ArrayList<>(); //每一行的高度 组成的List private List<Integer> mLineHeight = new ArrayList<Integer>(); //所有的View  private List<List<View>> mAllViews = new ArrayList<List<View>>(); //适配器 private MyTagAdapter mTagAdapter;

We'll take care of the adapter first, we provide an array of information

//需要显示的数据 private String[] mGuseeYourLoveVals = new String[]            {"Android", "Android移动", "Java", "UI设计师", "android实习",                    "android 移动","android安卓","安卓"};

The implementation of the adapter is very simple, we can emulate the Android system's own adapters

/**    抽象类*/public abstract class MyTagAdapter<T> {    //数据    private List<T> mTagDatas;    //构造函数    public MyTagAdapter(T[] datas) {        mTagDatas = new ArrayList<T>(Arrays.asList(datas));    }    //获取总数    public int getCount() {        return mTagDatas == null ? 0 : mTagDatas.size();    }    //抽象方法 获取View 由子类具体实现如何获得View    public abstract View getView(MyTagFlowLayout parent, int position, T t);    //获取数据中的某个Item    public T getItem(int position) {        return mTagDatas.get(position);    }}

We call the following statement in Mainactivity

//MyTagFlowLayout使我们自定义的ViewGroup,目前该类还是默认实现mGuseeYourLoveFlowLayout = (MyTagFlowLayout) findViewById(R.id.id_guess_your_love);//指定适配器,我们这里使用了匿名内部类的方式指定mGuseeYourLoveFlowLayout.setAdapter(new MyTagAdapter<String>(mGuseeYourLoveVals){    //获取LayoutInflater     final LayoutInflater mInflater = LayoutInflater.from(MainActivity.this);    //重点来了,我们在该匿名内部类中实现了MyTagAdapter的getView方法    @Override    public View getView(MyTagFlowLayout parent, int position, String s)    {        //在该方法中我们去加载了我们上面提到的layout/tag_view.xml,并返回TextView         TextView tv = (TextView) mInflater.inflate(R.layout.tag_view,                mGuseeYourLoveFlowLayout, false);        tv.setText(s);        return tv;    }});

Where Mytagflowlayout's Setadapter method is as follows, we analyze the mytagflowlayout definition process a little bit

public void setAdapter(MyTagAdapter adapter) {    removeAllViews();//先清空MyTagFlowLayout下的所有View    for (int i = 0; i < adapter.getCount(); i++) {        //这里的tagView 就是刚才的TextView        View tagView = adapter.getView(this, i, adapter.getItem(i));        //添加View        addView(tagView);    }}

At this point our mytagflowlayout data has been loaded, and the next is the display, the display is the most serious
Let's review the view display process Measure->layout->draw first. So obviously we have to measure first, then rewrite the Onmeasure method

    @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//Here we first get the measurement parameters given by the parent view, note that this         The parent view represents the Mytagflowlayout parent view int sizewidth = Measurespec.getsize (WIDTHMEASURESPEC);//Gets the width of the parent view passed to Mytagflowlayout int modewidth = Measurespec.getmode (WIDTHMEASURESPEC);//Gets the width measurement mode of the parent view passed to mytagflowlayout int sizeheight = Me Asurespec.getsize (HEIGHTMEASURESPEC);//Gets the height of the parent view passed to mytagflowlayout int modeheight = Measurespec.getmode (heightMeas        URESPEC);//Gets the height measurement mode of the parent view passed to mytagflowlayout int width = 0;        int height = 0;        int linewidth = 0;        int lineheight = 0;                Get all the sub view, in the process of the previous step we have added the sub view, according to the previous step of the data, here the ccount should be 8 int ccount = Getchildcount (); for (int i = 0; i < ccount; i++) {//loop to get each sub-View, this child points to the fact that we added above TextView View child = Getch             Ildat (i);            Measure each sub-view, Measurechild (Child, Widthmeasurespec, Heightmeasurespec); Get every sub-vieMeasuring width and height of w int childwidth = Child.getmeasuredwidth ();            int childheight = Child.getmeasuredheight ();  If the width of the current line + the width of the child to be added > the width of the mytagflowlayout-pading, indicating that the current line is "full", this "full" means that the current row cannot accommodate the next sub-view if (LineWidth + Childwidth > Sizewidth-getpaddingleft ()-getpaddingright ()) {//"full" requires a newline width = Math.max (width, line                 width),//mytagflowlayout the maximum value of the previous width and current linewidth linewidth = childwidth;//Resets the linewidth of the current row            Height + = lineheight;//mytagflowlayout Increase lineheight = childheight;//Resets the height of the current line's lineheight to Child view } else {//not full, the current line can hold the next child view LineWidth + = childwidth;//The width of the current line increases lineheight = Math.max (li                Neheight, childheight);//The height of the current row takes the maximum value of the height of the Child view} if (i = = cCount-1) {//If the current view is the last view width = Math.max (linewidth, width), length of//mytagflowlayout last width and current linewidth maximum height + = Lineheight ;//mytagflowlayIncrease in height of Out}}//Set mytagflowlayout height and width//If the width of mytagflowlayout is specified in XML, such as Android:layout_wid Th= "40DP" then use the specified width, otherwise the width of the measurement-padding, the height of the setting and width of the same setmeasureddimension (modewidth = = Measurespec.exact LY? Sizewidth:width + getpaddingleft () + getpaddingright (), modeheight = = measurespec.exactly?    Sizeheight:height + getpaddingtop () + getpaddingbottom ()); }

We have analyzed the Onmeasure method above, measure is the measurement, and the layout behind is the layouts, let's look at the layout

@Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {//Clears all list mallviews.clear () first;    Mlineheight.clear ();    Lineviews.clear ();    Get the width of the mytagflowlayout, this we have got int width = getwidth () in the Onmeasure method;    Line width and line height are initialized to 0 int linewidth = 0;    int lineheight = 0;    The same gets the number of all child view int ccount = Getchildcount (); for (int i = 0; i < ccount; i++) {//loop to get each sub-view, this child points to the fact that we added above TextView View child = Getchildat (i)        ;        View visibility If it is view.gone, ignore it if (child.getvisibility () = = View.gone) continue;        Get the measurement width and height of the child view int childwidth = Child.getmeasuredwidth ();        int childheight = Child.getmeasuredheight (); If the current line width is linewidth + the width of the current sub-view > The width of the mytagflowlayout-padding, then we should break the line to show if (Childwidth + linewidth > Width-g  Etpaddingleft ()-getpaddingright ()) {Mlineheight.add (lineheight);//Adds the current row height lineheight to the mlineheight that represents the current row height for all rows List of Mallviews.add (lineviews);//The sameAdd mallviews linewidth = 0;//Reset line width lineheight = childheight;//Reset line Height lineviews = new Arraylis T<view> ();//Reset Lineviews} linewidth + = childwidth;//Current line width linewidth add lineheight = Math. Max (Lineheight, childheight);; /Current Row height lineheight The maximum value of the previous row height and child view lineviews.add (children);//The handle view is added to the list of lineviews that represents the current child view Mlineheight.ad D (lineheight);//Add the current line high lineheight to the current row mallviews.add (lineviews);//Join mallviews//get paddingtop int top = GE    Tpaddingtop ();        Gets the number of all rows int linenum = Mallviews.size ();        for (int i = 0; i < linenum; i++) {//loops out each line lineviews = Mallviews.get (i);        The row height of each row is Lineheight = Mlineheight.get (i);                Get paddingleft int left = Getpaddingleft ();            for (int j = 0; J < Lineviews.size (); j + +) {//Loop out the child view view from each line Lineviews.get (j);            if (child.getvisibility () = = View.gone) {    Continue  }//Call the child's layout, here is actually called Textview.layout Child.layout (left, top, LC + Child.getmeasuredwidth (), TC                        + child.getmeasuredheight ()); Left + = Child.getmeasuredwidth ();//left increment} top + = Lineheight;//top Increment}}

All right, let's run it.

The effect is not as we gave at the beginning of the article, but at least a similar one. The next thing to consider is how to add the appropriate spacing for these sub-view ... I believe that smart readers will be able to solve this problem on their own. Here a little hint of spacing->margin?? If in doubt, please leave a message.

This article summarizes
In this article we explore some of the knowledge and ideas of custom viewgroup, unfortunately, many of the code in this article is not a best practice, I hope you elegance readers. And about the view of the incident, I find a long time really can not find a good example to share to everyone, if you have a good idea, please hit me in the comment area, it is best to view the drawing system and event system perfect combination , simple and clear , "blood circulation and stasis" Example of a custom viewgroup: I am here to apologize to the readers who have failed to live up to expectations.

Next trailer
If someone provides ideas, then we still come from the definition of viewgroup, if not, (my blog seems to have been very few people comment), we come to a little rest, to see common development often encountered in memory leaks and related solutions.

Sincerely, salute.

Android development of long-distance foreign--custom view of various poses 2

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.