Kotlin returns JSON dynamic layout interface through interface

introduction


When I wrote the first Kotlin article , I already planned to do a project to practice well, so I chose the Open Eye app as a hands-on training project to use Kotlin throughout the process.

The page data has been obtained in the previous article . Since its page is dynamically laid out through JSON (personal point of view), it requires: skilled JSON parsing ability and the ability to customize controls

I'm going to make a fool of myself here

text


First look at the comparison chart
open eyes

my imitation

Click the button to get the data. The above data indicates that
the content of the child View pages contained in the root ViewGroup is still a lot.

Take a look at how many controls are used on this page in total

image.png

Exactly 10, don't worry that there will be a lot of custom controls in the end, because other pages are also using these controls at the same time. How to encapsulate the control? How to initialize the control? These two issues are particularly important, otherwise the different interfaces will not only be difficult to develop, but also difficult to maintain in the future.

ideas

  • The effect I want to achieve is very simple, convert it into View through a JSONObject
  • The JSONObject contains the type and data of the View (eye-opening JSON structure does this)
  • Create a model containing the type and data of the View

accomplish

1. The structure of the JSONObject returned by the analysis of JSON
is like this, a list and the total number of lists
image.png

Specific JSONObject contains a JSONObject of type and data
image.png

The JSONObject of data contains a dataType to indicate the specific data type, which is the itemList in the figure. The JSONObjects of different dataTypes are also different. The key point is to understand
image.png

2. Create mode ViewData

/**
 * Created by mr.lin on 2018/1/7.
 * 控件数据
 */
data class ViewData(private var jsonObject: JSONObject) {
    var type = jsonObject.getString("type")
    var json = jsonObject.getJSONObject("data")
}

3. Split JSON into ViewData array

        var json = JSONObject(string)
        var jsonArray = json.getJSONArray("itemList")
        for (i in 0 until jsonArray.length()) {
            var viewData = ViewData(jsonArray.getJSONObject(i))
            viewDatas.put(i, viewData)
        }

4. Create helper classes to return different types of Views

/**
 * Created by mr.lin on 2018/1/8.
 * 将json转成View
 */
class JsonViewUtils {

    companion object {
        fun viewDataToView(context: Context, viewData: ViewData): View? {
            when (viewData.type) {
                "horizontalScrollCard" -> return ViewHorizontalScrollCard(context, viewData.json)
                "banner2" -> return ViewBanner2(context, viewData.json)
                "textCard" -> return ViewTextCard(context, viewData.json)
                "briefCard" -> return ViewBriefCard(context, viewData.json)
                "followCard" -> return ViewFollowCard(context, viewData.json)
                "videoSmallCard" -> return ViewVideoSmallCard(context, viewData.json)
                "squareCardCollection" -> return ViewSquareCardCollection(context, viewData.json)
                "videoCollectionWithBrief" -> return ViewVideoCollectionWithBrief(context, viewData.json)
                "video" -> return ViewVideo(context, viewData.json)
                "DynamicInfoCard" -> return ViewDynamicInfoCard(context, viewData.json)
            }
            return null
        }
    }

}

5. Customize the specific View

Take a specific View to see
ViewSquareCardCollection

Layout structure: From top to bottom, a TextView at the top, a line at the bottom, and a HorizontalScrollView in the middle

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/titleTv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:drawablePadding="10dp"
            android:drawableRight="@mipmap/goto_icon"
            android:textSize="22sp"
            android:textStyle="bold" />

        <HorizontalScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:scrollbars="none">

            <LinearLayout
                android:id="@+id/containerLl"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:paddingLeft="7dp"
                android:paddingRight="15dp" />
        </HorizontalScrollView>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_marginTop="12dp"
            android:background="@color/cededed" />

    </LinearLayout>

</FrameLayout>

HorizontalScrollView wraps ViewBanner2, which reflects the advantages of JsonViewUtils very well.

/**
 * Created by mr.lin on 2018/1/10.
 */
class ViewSquareCardCollection(context: Context, json: JSONObject, attrs: AttributeSet?, defStyleAttr: Int) : FrameLayout(context, attrs, defStyleAttr) {

    constructor(context: Context, json: JSONObject, attrs: AttributeSet?) : this(context, json, attrs, 0)
    constructor(context: Context, json: JSONObject) : this(context, json, null)

    init {
        LayoutInflater.from(context).inflate(R.layout.view_squarecardcollection, this, true)

        titleTv.text = json.getJSONObject("header").getString("title")

        var itemList = json.getJSONArray("itemList")
        for (i in 0 until itemList.length()) {
            var viewData = ViewData(itemList.getJSONObject(i))
            containerLl.addView(JsonViewUtils.viewDataToView(context, viewData))
        }

    }

}

to be optimized

1. Now all data transmission is JSON, and you can extract an entity class.
2. Now only the data that needs to be displayed is taken out, and the data required for business is not stored
. 3. Dead page

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325995902&siteId=291194637