FlowLayout inherits from ViewGroup, it can quickly help you to realize Tablayout and Label labels, including a variety of effects, help you quickly realize APP UI functions, let you focus on code architecture, say goodbye to tedious UI.

If you want to write your own, check out the following articles

Implement a customizable TabFlowLayout(a) – measurement and layout

Implement a customizable TabFlowLayout(two) – to achieve scrolling and smooth transition

Implement a customizable TabFlowLayout(three) — dynamic data add and common interface encapsulation

Implement a customizable TabFlowLayout(four) – combined with ViewPager, achieve cool effect

Implement a customizable TabFlowLayout – Principles

Implement a customizable TabFlowLayout – documentation

FlowLayout and Recyclerview to achieve double table linkage

If you also want to implement banners quickly, you can use this library github.com/LillteZheng…

A correlation

allprojects {
    repositories {
       ...
        maven { url 'https://jitpack.io'}}}Copy the code

The latest version is subject to the project: Code engineering: To implement a customizable FlowLayout

implementation 'com. Making. LillteZheng: FlowHelper: v1.17'
Copy the code

Second, the effect of

First, is the effect of TabFlowLayout, its layout support vertical and horizontal two ways, first look at the effect of support:

No ViewPager Combining with the ViewPager
TabFlowLayout vertical, RecyclerView linkage effect

In addition to TabFlowLayout, there are LAbelFlowLayout tabbed layout, support for line wrapping and display more

LabelFlowLayout LabelFlowLayout shows more

As you can see, TabFlowLayout currently supports the following effects:

  • rectangular
  • triangle
  • Rounded corners
  • Shape or Bitmap resource files
  • Custom function
  • Enlarge the Item effect, which can be used with the above effect
  • Color gradient effect, need to use the TabColorTextView control, and the above effect can be shared, only support viewPager situation
  • For vertical effect, tab_orientation = vertical is required

Three, use,

Mainly TabFlowLayout and LabelFlowLayout these two controls

3.1 TabFlowLayout

TabFlowLayout: TabFlowLayout = “vertical”; TabFlowLayout: TabFlowLayout = “vertical”; TabFlowLayout: TabFlowLayout = “vertical”;

XML

<com.zhengsr.tablib.view.flow.TabFlowLayout
    android:id="@+id/resflow"
    android:layout_width="wrap_content"
    android:layout_marginTop="5dp"
    android:background="#6D8FB0"
    android:layout_height="wrap_content"/>
Copy the code

For example, to add a rectangle or triangle, use the app:tab_type property, such as a rectangle:

<com.zhengsr.tablib.view.flow.TabFlowLayout
    android:id="@+id/rectflow"
    android:layout_width="wrap_content"
    android:layout_marginTop="5dp"
    app:tab_type="rect"
    app:tab_color="@color/colorPrimary"
    app:tab_height="3dp"
    app:tab_width="20dp"
    app:tab_margin_b="3dp"
    android:background="@color/black_ff_bg"
    app:tab_scale_factor="1.2"
    app:tab_item_autoScale="true"
    android:layout_height="wrap_content"/>
Copy the code

The key custom parameters are explained here

  • Tab_type: Specifies the effect type. Rect is used here
  • Tab_color: indicates the color of a TAB
  • Tab_width: the width of the TAB. If left blank, the default control width
  • Tab_height: indicates the height of the TAB
  • Tab_margin_b: margin_bottom, l,t,r,b
  • Tab_item_autoScale: whether to automatically zoom in or out effects. Default: false
  • Tab_scale_factor: magnification factor, which is 1.2 times. Default is 1

These are the basic attributes. You can also set tri here. When type is round or res, width and height can be left out because the control has to be sized accordingly.

For additional instructions, see the custom attribute description below.

Java

So, once you’re done in XML, then, in your Activity, write:

private void rectFlow(){ TabFlowLayout flowLayout = findViewById(R.id.rectflow); // Set the datasetFlowlayout. setAdapter(new TabFlowAdapter<String>(r.layout. item_msg,mTitle) {@override public void onItemSelectState(View view, boolean isSelected) { super.onItemSelectState(view, isSelected); // When you select it, you can change colors, and if your background is selector, you don't have to do thatif (isSelected){
                setTextColor(view,R.id.item_text,Color.WHITE);
            }else{
                setTextColor(view,R.id.item_text,getResources().getColor(R.color.unselect));
            }
        }

        @Override
        public void bindView(View View, String data, int position) {/** * Bind data, can be usedsetText(..) Also, when your child controls need to click the event, register the event with addChildrenClick() and override onItemChildClick(..). Can get the event, otherwise write your own. * Your own clicks and long presses do not need to be registered */setText(view,R.id.item_text,data)
                    .setTextColor(view,R.id.item_text,getResources().getColor(R.color.unselect));
            if (position == 0){
                setVisible(view,R.id.item_msg,true); } // Register the childrenClick (view, r.id_text,position); //addChildrenLongClick(view, r.id_text,position); }}); }Copy the code

As you can see, all you need to do is set the Adapter. Note that you need to pass in the layout of the child control, so that you can customize your layout, such as a TextView and a red dot. For details, see this:

Implement a customizable TabFlowLayout(three) — dynamic data add and common interface encapsulation

If you want to use a color gradient effect, change the TextView to TabColorTextView, for example:

<? xml version="1.0" encoding="utf-8"? > <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.zhengsr.tablib.view.TabColorTextView
        android:id="@+id/item_text"
        android:layout_width="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        tools:text="Test"
        android:paddingTop="6dp"
        android:paddingBottom="6dp"
        android:paddingStart="12dp"
        android:paddingEnd="12dp"
        android:textSize="14sp"
        app:colortext_default_color="@color/unselect"
        app:colortext_change_color="@color/colorAccent"
        android:gravity="center"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/item_msg"
        android:layout_width="5dp"
        android:layout_height="5dp"
        android:gravity="center"
        android:textSize="8dp"
        android:background="@drawable/shape_red_radius"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="5dp"
        android:visibility="gone"
       />



</android.support.constraint.ConstraintLayout>
Copy the code

3.1.1. Combine Viewpager

Combining ViewPager is very simple, as follows:

flowLayout.setViewPager(...) Can.Copy the code

It has several methods, just refer to this explanation.

/** * configureViewpager * @param viewpager * @param textId The ID of the textView used for textView color changes * @param selectedIndex The default selected item, with an initial value of 0, can also be selected from the second page or elsewhere * @param unselectedColor @param selectedColor is not required for TabColorTextView. */ public void is not required for TabColorTextViewsetViewPager(
                        ViewPager viewPager,
                        int textId, 
                        int selectedIndex, 
                        int unselectedColor, 
                        int selectedColor) {}
Copy the code

To avoid stalling, when combining viewpager with fragment, you can optimize the following methods:

  • Fragment When the network layout is complex or data is being loaded, you are advised to initialize or load data in lazy loading
  • Viewpager increases the cache, setOffscreenPageLimit(3).
  • SetCurrentItem (position,false), scroll to false, then animate the item with flowLayout, FlowLayout.setitemanim (Position)

If you feel viewpager switch too fast, you can use ViewPagerHelperUtils. InitSwitchTime (getContext (), viewpager, 600) change the scrolling speed

3.1.2 Dynamic configuration of custom properties

If you don’t want to do this in XML, you can use TabBean to configure it directly. For example, tab_type=res and your drawable using Shape is configured as follows:

private void resFlow(){ final TabFlowLayout flowLayout = findViewById(R.id.resflow); flowLayout.setViewPager(mViewPager); /** * Configure custom attributes */ TabBean bean = new TabBean(); bean.tabType = FlowConstants.RES; bean.tabItemRes = R.drawable.shape_round; // Ms bean.tabClickAnimTime = 300; bean.tabMarginLeft = 5; bean.tabMarginTop = 12; bean.tabMarginRight = 5; bean.tabMarginBottom = 10; // Dynamically set the custom property flowLayout.settabBean (bean); flowLayout.setAdapter(new TabFlowAdapter<String>(R.layout.item_msg,mTitle) { @Override public voidbindView(View view, String data, int position) {
            setText(view,R.id.item_text,data); } @Override public void onItemClick(View view, String data, int position) { super.onItemClick(view, data, position); mViewPager.setCurrentItem(position); }}); }Copy the code

3.1.3. Customize Actions

What if it doesn’t have what you want? , so the project also supports user customization, for example, to customize a white dot effect, just need to inherit BaseAction, the dot in the effect picture above is actually written after inheriting BaseAction, the code is as follows:

/** * Draw a circular indicator * Besides inheriting BaseAction, TabRect */ class CircleAction extends BaseAction{@override public void config(TabFlowLayout parentView) { super.config(parentView); View child = parentView.getChildAt(0);if(child ! = null) {float l = parentView.getPaddingLeft() + child.getMeasuredWidth()/2;
                float t = parentView.getPaddingTop() +  child.getMeasuredHeight() - mTabHeight/2 -mMarginBottom;
                float r = mTabWidth + l;
                floatb = child.getMeasuredHeight() - mMarginBottom; Mtabrect. set(l,t,r,b); } } @Override protected void valueChange(TabValue value) { super.valueChange(value); /** * value Specifies the left and right values of the child control when it scrolls. Mtabrect. left = value. Left + mTabWidth/2; } @Override public void draw(Canvas canvas) { canvas.drawCircle(mRect.left,mRect.top,mTabWidth/2,mPaint); }}Copy the code

Get the move offset by overriding valueChange and then using FlowLayout.setAction (new CircleAction()). If it’s vertical, go to value.top, value.bottom and write the logic.

3.1.4 reference Code

For the above effect, you can refer to the following code:

There is layout code for the ViewPager

The Activity of a ViewPager

3.2 TabFlowLayout vertical effect

Just set tab_orientation to vertical. When type is rect or TRi, You can also select left or right effects with tab_tab_action_orientaion:

    <com.zhengsr.tablib.view.flow.TabFlowLayout
        android:id="@+id/tabflow"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:tab_type="rect"
        app:tab_color="@color/colorPrimary"
        app:tab_orientation="vertical"
        app:tab_width="2dp"
        app:tab_height="20dp"
        app:tab_action_orientaion="left"
        android:background="@color/page_gray_cccc"
        />
Copy the code

The effect is as follows:

And recyclerView linkage effect, can refer to this:

Recyclerview dual table linkage

3.3 LabelFlowLayout

LabelFlowLayout vertical layout, support automatic line wrapping, single selection, multiple selection, long press and other functions.

Its state changes according to the selected view, so you can either write the selector as the background, or you can set it in the method

3.3.1 use

LabelFlowLayout is a default radio option, configured in XML like this:

<com.zhengsr.tablib.view.flow.LabelFlowLayout
    android:id="@+id/singleflow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
/>
Copy the code

FlowLayout also uses Adapter to configure data:

LabelFlowLayout flowLayout = findViewById(R.id.singleflow); final LabelFlowAdapter adapter; Flowlayout.setadapter (adapter = new LabelFlowAdapter<String>(r.layout.item_textView,mTitle){/** * Bind data, can be usedsetText(..) Also, when your child controls need to click the event, register the event with addChildrenClick() and override onItemChildClick(..). Can get the event, otherwise write your own. */ @override public void OverridebindView(View view, String data, int position) {
        setText(view,R.id.item_text,data); //addChildrenClick(view, r.i.LAST_text,position); } @Override public void onItemSelectState(View view, boolean isSelected) { super.onItemSelectState(view, isSelected); TextView textView = view.findViewById(R.id.item_text);if (isSelected) {
            textView.setTextColor(Color.WHITE);
        } else{ textView.setTextColor(Color.GRAY); }}});Copy the code

3.3.2 rainfall distribution on 10-12 multi-select

You only need to configure the flowLayout. SetMaxSelectCount (3); Then rewrite the adapter:

@Override
public void onReachMacCount(List<Integer> ids, int count) {
    super.onReachMacCount(ids, count);
    Toast.makeText(LabelActivity.this, "Only selected at most."+count+"A"+"Selected coordinates:"+ids, Toast.LENGTH_SHORT).show();
}
Copy the code

If you select some of the items by default, use flowlayout.setselects (2,3,5);

3.3.3 long-press

Hold down view, and write the state changes yourself:

    private void canLongFlow(){
        LabelFlowLayout flowLayout = findViewById(R.id.longflow);
        flowLayout.setAdapter(new LabelFlowAdapter<String>(R.layout.item_search_layout,mTitle2) {
            @Override
            public void bindView(View view, String data, int position) {
                setText(view,R.id.search_msg_tv,data)
                        .addChildrenClick(view,R.id.search_delete_iv,position);
            }

            @Override
            public void onItemSelectState(View view, boolean isSelected) {
                super.onItemSelectState(view, isSelected);
                if(! isSelected){ view.setBackgroundResource(R.drawable.shape_search);setVisible(view,R.id.search_delete_iv,false);
                }
            }

            @Override
            public void onItemClick(View view, String data, int position) {
                super.onItemClick(view, data, position);
                Toast.makeText(LabelActivity.this, "Click:"+data, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemChildClick(View childView, int position) {
                super.onItemChildClick(childView, position);
                if(childView.getId() == R.id.search_delete_iv){ mTitle2.remove(position); notifyDataChanged(); }} @override public Boolean onItemLongClick(View View,int position)false
                 */
                resetStatus();
                view.setBackgroundResource(R.drawable.shape_search_select);
                setVisible(view,R.id.search_delete_iv,true);
                returnsuper.onItemLongClick(view,position); }}); }Copy the code

3.3.5 Display More Information

LabelFlowLayout also supports displaying more functions, as shown below:

The configured XML is as follows:

<com.zhengsr.tablib.view.flow.LabelFlowLayout
    android:id="@+id/labelflow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:layout_marginStart="10dp"
    app:label_showLine="2"
    app:label_showMore_layoutId="@layout/show_more"
    app:label_showMore_Color="@color/white"/>
Copy the code
  • Label_showLine indicates the maximum number of lines to display
  • Label_showMore_layoutId: Displays more layoutiDs for customization
  • Label_showMore_Color represents the primary background color and is used to set shader to be dashed

Label_showMore_Color converts more layoutids into bitmaps and displays them below; What about the blur?

Create a shader for paint with a transparent color on top and a background color on the bottom. Such as:

/** * add a shader, */ Shader Shader = new LinearGradient(0, 0, 0, getHeight(), color.transparent, mShowMoreColor, Shader.TileMode.CLAMP); mPaint.setShader(shader);Copy the code

3.3.6 Configuring User-defined Attributes

Of course, dynamic configuration of custom properties is also supported. As follows:

LabelBean bean = new LabelBean();
bean.showLines = 2;
bean.showMoreLayoutId = R.layout.show_more;
bean.showMoreColor = Color.WHITE;
flowLayout.setLabelBean(bean);
Copy the code

3.3.7 Reference Code:

Layout code

The Activity code

Methods supported by Adpater

TabFlowLayout and LAbelFlowLayout are used to load data through setAdapter, except for setText(..). ,setTextColor(..) ,setImageView, etc., also supports the click event, specific methods, can refer to the following code:

Adapter method

Custom property list

TabFlowLayout

The name of the type instructions
tab_type rect,tri,round,color,res Type of TAB, currently supports rectangle, triangle, rounded corner, color gradient, resource RES
tab_color color The color of the indicator can be defined when the type is RECt, TRI, or ROUD
tab_width dimension The width of the indicator, if not written, according to the size of the control itself
tab_height dimension Indicator height
tab_item_res reference The background of the indicator, such as Shape, bitmap, etc., only works on the RES
tab_round_size dimension The size of the rounded corner only affects the round
tab_margin_l dimension The left deviation
tab_margin_t dimension The migration
tab_margin_r dimension Right sides
tab_margin_b dimension Under the migration
tab_click_animTime integer Click on the animation time, default 300ms
tab_item_autoScale boolean Turn on zooming in and out effects
tab_scale_factor float magnification
tab_orientation integer Vertical Indicates the vertical defense line. Horizontal indicates the default horizontal line
tab_action_orientaion integer Left coordinate, right right, only support trI, RECT two effects
tab_isAutoScroll boolean Whether automatic scrolling is supported. Default is true

TabColorTextView

The name of the type instructions
colortext_default_color color The default color
colortext_change_color color I need a gradient color

LabelFlowLayout

The name of the type instructions
label_maxcount integer Maximum number of choices
label_iaAutoScroll boolean Whether automatic scrolling is supported
label_showLine integer The maximum number of rows to display
label_showMore_layoutId integer Display more layoutId
label_showMore_Color color Show more background color for blurring effect