├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── array.json │ └── json.json │ ├── java │ └── com │ │ └── dandan │ │ └── jsonhandleview │ │ └── MainActivity.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ └── activity_main.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jsonhandleview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── dandan │ │ └── jsonhandleview │ │ └── library │ │ ├── JsonView.java │ │ └── JsonViewLayout.java │ └── res │ ├── drawable-xxhdpi │ ├── jsonview_item_collapse.xml │ ├── jsonview_item_expand.xml │ └── jsonview_select_bg.xml │ ├── layout │ └── item_view_jsonview_layout.xml │ └── values │ └── strings.xml ├── screenshots ├── json-expand.gif ├── json-handle.gif └── json-handle.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JsonHandleView 2 | It's like json-handle, to convert json strings to a friendly readable format, it supports expend&collapsed json strings. 3 | 4 | https://chrome.google.com/webstore/detail/json-handle/iahnhfdhidomcpggpaimmmahffihkfnj 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ## Dependencies 13 | 14 | ```java 15 | implementation 'com.tzx.json:jsonhandleview:1.2.2' 16 | ``` 17 | 18 | ## Usage 19 | 20 | **Step1** 21 | 22 | ```xml 23 | 24 | 29 | 30 | 34 | 35 | 36 | ``` 37 | 38 | **step2** 39 | 40 | ```java 41 | JsonViewLayout jsonViewLayout = findViewById(R.id.jsonView); 42 | jsonViewLayout.bindJson("your json strings." || JSONObject || JSONArray); 43 | ``` 44 | 45 | ## Code Style 46 | 47 | The default code style is like [JSON-handle](https://chrome.google.com/webstore/detail/json-handle/iahnhfdhidomcpggpaimmmahffihkfnj). 48 | 49 | ```java 50 | // Color 51 | jsonViewLayout.setKeyColor() 52 | jsonViewLayout.setObjectKeyColor() 53 | jsonViewLayout.setValueTextColor() 54 | jsonViewLayout.setValueNumberColor() 55 | jsonViewLayout.setValueNullColor() 56 | jsonViewLayout.setValueBooleanColor() 57 | jsonViewLayout.setArrayLengthColor() 58 | 59 | // TextSize 60 | jsonViewLayout.setTextSize() 61 | 62 | //expand/collapse 63 | jsonViewLayout.expandAll(); 64 | jsonViewLayout.collapseAll(); 65 | ``` 66 | 67 | ## LICENSE 68 | 69 | ```lis 70 | Copyright 2018 stven0king, All right reserved. 71 | 72 | Licensed under the Apache License, Version 2.0 (the "License"); 73 | you may not use this file except in compliance with the License. 74 | You may obtain a copy of the License at 75 | 76 | http://www.apache.org/licenses/LICENSE-2.0 77 | 78 | Unless required by applicable law or agreed to in writing, software 79 | distributed under the License is distributed on an "AS IS" BASIS, 80 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 81 | See the License for the specific language governing permissions and 82 | limitations under the License. 83 | ``` 84 | 85 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | android { 3 | compileSdkVersion 28 4 | defaultConfig { 5 | applicationId "com.dandan.jsonhandleview" 6 | minSdkVersion 15 7 | targetSdkVersion 22 8 | versionCode 1 9 | versionName "1.0" 10 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | debug { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | 22 | } 23 | 24 | lintOptions { 25 | abortOnError false 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | implementation 'com.android.support:appcompat-v7:28.0.0-rc02' 32 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 33 | // implementation project(path: ':jsonhandleview') 34 | implementation 'com.tzx.json:jsonhandleview:1.2.2' 35 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/assets/array.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "jobid": "31684803546191", 4 | "jobtitle": "美发助理", 5 | "jobtype": 1, 6 | "looknum": 36, 7 | "updatetime": "2018-08-22", 8 | "unreadnum": 0, 9 | "jobstate": 1, 10 | "jobclass": 1, 11 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=31684803546191", 12 | "infostate": 1, 13 | "murl": "http://m.58.com/bj/meirongjianshen/31684803546191x.shtml?v=1535531967187", 14 | "sal": "30-60元", 15 | "jz": 0, 16 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/31684803546191", 17 | "supportjz": 1, 18 | "shelvesstate": 0, 19 | "isRed": 0, 20 | "isCap": 0, 21 | "isShowCap": 1, 22 | "gjshelfstate": 0, 23 | "mvip": 0, 24 | "zcmGjPromotionTop": { 25 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=31684803546191", 26 | "isshowgjsettop": "1", 27 | "cangjsettop": "1" 28 | }, 29 | "bizstate": { 30 | "istop": 0, 31 | "isadvt": 0, 32 | "iscpc": 0, 33 | "cantop": 1, 34 | "canadvt": 0, 35 | "cancpc": 1, 36 | "mvip": 0 37 | }, 38 | "workplace": "北京", 39 | "years": "不限", 40 | "totalresume": 0, 41 | "shareCount": 0 42 | }, 43 | { 44 | "jobid": "34704592402748", 45 | "jobtitle": "销售总监", 46 | "jobtype": 1, 47 | "looknum": 0, 48 | "updatetime": "2018-07-17", 49 | "unreadnum": 0, 50 | "jobstate": 0, 51 | "jobclass": 1, 52 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=34704592402748", 53 | "infostate": 0, 54 | "murl": "http://m.58.com/bj/yewu/34704592402748x.shtml?v=1535531967192", 55 | "sal": "8000-12000元", 56 | "jz": 0, 57 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/34704592402748", 58 | "supportjz": 0, 59 | "shelvesstate": 0, 60 | "isRed": 0, 61 | "isCap": 0, 62 | "isShowCap": 0, 63 | "gjshelfstate": 0, 64 | "mvip": 0, 65 | "zcmGjPromotionTop": { 66 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=34704592402748", 67 | "isshowgjsettop": "1", 68 | "cangjsettop": "0" 69 | }, 70 | "bizstate": { 71 | "istop": 0, 72 | "isadvt": 0, 73 | "iscpc": 0, 74 | "cantop": 0, 75 | "canadvt": 0, 76 | "cancpc": 0, 77 | "mvip": 0 78 | }, 79 | "workplace": "北京", 80 | "years": "不限", 81 | "totalresume": 0, 82 | "shareCount": 0 83 | }, 84 | { 85 | "jobid": "34051057026994", 86 | "jobtitle": "测试员", 87 | "jobtype": 1, 88 | "looknum": 577, 89 | "updatetime": "2018-06-15", 90 | "unreadnum": 0, 91 | "jobstate": 1, 92 | "jobclass": 1, 93 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=34051057026994", 94 | "infostate": 1, 95 | "murl": "http://m.58.com/bj/tech/34051057026994x.shtml?v=1535531967201", 96 | "sal": "5000-8000元", 97 | "jz": 0, 98 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/34051057026994", 99 | "supportjz": 1, 100 | "shelvesstate": 1, 101 | "isRed": 0, 102 | "isCap": 0, 103 | "isShowCap": 1, 104 | "gjshelfstate": 1, 105 | "mvip": 0, 106 | "zcmGjPromotionTop": { 107 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=34051057026994", 108 | "isshowgjsettop": "1", 109 | "cangjsettop": "2" 110 | }, 111 | "bizstate": { 112 | "istop": 0, 113 | "isadvt": 0, 114 | "iscpc": 0, 115 | "cantop": 1, 116 | "canadvt": 0, 117 | "cancpc": 1, 118 | "mvip": 0 119 | }, 120 | "workplace": "北京", 121 | "years": "10年以上", 122 | "totalresume": 6, 123 | "shareCount": 0 124 | }, 125 | { 126 | "jobid": "29859112810921", 127 | "jobtitle": "服务员", 128 | "jobtype": 1, 129 | "looknum": 21, 130 | "updatetime": "2018-05-15", 131 | "unreadnum": 0, 132 | "jobstate": 0, 133 | "jobclass": 1, 134 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=29859112810921", 135 | "infostate": 0, 136 | "murl": "http://m.58.com/bj/zplvyoujiudian/29859112810921x.shtml?v=1535531967207", 137 | "sal": "3000-5000元", 138 | "jz": 0, 139 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/29859112810921", 140 | "supportjz": 0, 141 | "shelvesstate": 0, 142 | "isRed": 0, 143 | "isCap": 0, 144 | "isShowCap": 0, 145 | "gjshelfstate": 0, 146 | "mvip": 0, 147 | "zcmGjPromotionTop": { 148 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=29859112810921", 149 | "isshowgjsettop": "1", 150 | "cangjsettop": "0" 151 | }, 152 | "bizstate": { 153 | "istop": 0, 154 | "isadvt": 0, 155 | "iscpc": 0, 156 | "cantop": 0, 157 | "canadvt": 0, 158 | "cancpc": 0, 159 | "mvip": 0 160 | }, 161 | "workplace": "北京", 162 | "years": "不限", 163 | "totalresume": 1, 164 | "shareCount": 0 165 | }, 166 | { 167 | "jobid": "30147482837708", 168 | "jobtitle": "洗衣工", 169 | "jobtype": 1, 170 | "looknum": 91, 171 | "updatetime": "2017-10-09", 172 | "unreadnum": 0, 173 | "jobstate": 0, 174 | "jobclass": 1, 175 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=30147482837708", 176 | "infostate": 0, 177 | "murl": "http://m.58.com/bj/jiazhengbaojiexin/30147482837708x.shtml?v=1535531967225", 178 | "sal": "3000-5000元", 179 | "jz": 0, 180 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/30147482837708", 181 | "supportjz": 0, 182 | "shelvesstate": 0, 183 | "isRed": 0, 184 | "isCap": 0, 185 | "isShowCap": 0, 186 | "gjshelfstate": 0, 187 | "mvip": 0, 188 | "zcmGjPromotionTop": { 189 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=30147482837708", 190 | "isshowgjsettop": "1", 191 | "cangjsettop": "0" 192 | }, 193 | "bizstate": { 194 | "istop": 0, 195 | "isadvt": 0, 196 | "iscpc": 0, 197 | "cantop": 0, 198 | "canadvt": 0, 199 | "cancpc": 0, 200 | "mvip": 0 201 | }, 202 | "workplace": "北京", 203 | "years": "不限", 204 | "totalresume": 0, 205 | "shareCount": 0 206 | }, 207 | { 208 | "jobid": "30003190902469", 209 | "jobtitle": "服务员", 210 | "jobtype": 1, 211 | "looknum": 215, 212 | "updatetime": "2017-08-10", 213 | "unreadnum": 0, 214 | "jobstate": 3, 215 | "jobclass": 1, 216 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=30003190902469", 217 | "infostate": 5, 218 | "murl": "http://m.58.com/ab/zplvyoujiudian/30003190902469x.shtml?v=1535531967232", 219 | "sal": "面议", 220 | "jz": 0, 221 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/30003190902469", 222 | "supportjz": 0, 223 | "shelvesstate": 0, 224 | "isRed": 0, 225 | "isCap": 0, 226 | "isShowCap": 0, 227 | "gjshelfstate": 0, 228 | "mvip": 0, 229 | "zcmGjPromotionTop": { 230 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=30003190902469", 231 | "isshowgjsettop": "1", 232 | "cangjsettop": "0" 233 | }, 234 | "bizstate": { 235 | "istop": 0, 236 | "isadvt": 0, 237 | "iscpc": 0, 238 | "cantop": 0, 239 | "canadvt": 0, 240 | "cancpc": 0, 241 | "mvip": 0 242 | }, 243 | "workplace": "阿坝", 244 | "years": "3-5年", 245 | "totalresume": 9, 246 | "shareCount": 0 247 | }, 248 | { 249 | "jobid": "29439352378701", 250 | "jobtitle": "服务员", 251 | "jobtype": 1, 252 | "looknum": 0, 253 | "updatetime": "2017-03-20", 254 | "unreadnum": 0, 255 | "jobstate": 0, 256 | "jobclass": 1, 257 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=29439352378701", 258 | "infostate": 0, 259 | "murl": "http://m.58.com/bj/zplvyoujiudian/29439352378701x.shtml?v=1535531967237", 260 | "sal": "面议", 261 | "jz": 0, 262 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/29439352378701", 263 | "supportjz": 0, 264 | "shelvesstate": 0, 265 | "isRed": 0, 266 | "isCap": 0, 267 | "isShowCap": 0, 268 | "gjshelfstate": 0, 269 | "mvip": 0, 270 | "zcmGjPromotionTop": { 271 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=29439352378701", 272 | "isshowgjsettop": "1", 273 | "cangjsettop": "0" 274 | }, 275 | "bizstate": { 276 | "istop": 0, 277 | "isadvt": 0, 278 | "iscpc": 0, 279 | "cantop": 0, 280 | "canadvt": 0, 281 | "cancpc": 0, 282 | "mvip": 0 283 | }, 284 | "workplace": "北京", 285 | "years": "不限", 286 | "totalresume": 0, 287 | "shareCount": 0 288 | } 289 | ] -------------------------------------------------------------------------------- /app/src/main/assets/json.json: -------------------------------------------------------------------------------- 1 | { 2 | "resultcode": 0, 3 | "result": { 4 | "authtype": 2, 5 | "authstate": 1, 6 | "tabState": 2, 7 | "list": [ 8 | { 9 | "jobid": "31684803546191", 10 | "jobtitle": "美发助理", 11 | "jobtype": 1, 12 | "looknum": 36, 13 | "updatetime": "2018-08-22", 14 | "unreadnum": 0, 15 | "jobstate": 1, 16 | "jobclass": 1, 17 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=31684803546191", 18 | "infostate": 1, 19 | "murl": "http://m.58.com/bj/meirongjianshen/31684803546191x.shtml?v=1535531967187", 20 | "sal": "30-60元", 21 | "jz": 0, 22 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/31684803546191", 23 | "supportjz": 1, 24 | "shelvesstate": 0, 25 | "isRed": 0, 26 | "isCap": 0, 27 | "isShowCap": 1, 28 | "gjshelfstate": 0, 29 | "mvip": 0, 30 | "zcmGjPromotionTop": { 31 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=31684803546191", 32 | "isshowgjsettop": "1", 33 | "cangjsettop": "1" 34 | }, 35 | "bizstate": { 36 | "istop": 0, 37 | "isadvt": 0, 38 | "iscpc": 0, 39 | "cantop": 1, 40 | "canadvt": 0, 41 | "cancpc": 1, 42 | "mvip": 0 43 | }, 44 | "workplace": "北京", 45 | "years": "不限", 46 | "totalresume": 0, 47 | "shareCount": 0 48 | }, 49 | { 50 | "jobid": "34704592402748", 51 | "jobtitle": "销售总监", 52 | "jobtype": 1, 53 | "looknum": 0, 54 | "updatetime": "2018-07-17", 55 | "unreadnum": 0, 56 | "jobstate": 0, 57 | "jobclass": 1, 58 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=34704592402748", 59 | "infostate": 0, 60 | "murl": "http://m.58.com/bj/yewu/34704592402748x.shtml?v=1535531967192", 61 | "sal": "8000-12000元", 62 | "jz": 0, 63 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/34704592402748", 64 | "supportjz": 0, 65 | "shelvesstate": 0, 66 | "isRed": 0, 67 | "isCap": 0, 68 | "isShowCap": 0, 69 | "gjshelfstate": 0, 70 | "mvip": 0, 71 | "zcmGjPromotionTop": { 72 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=34704592402748", 73 | "isshowgjsettop": "1", 74 | "cangjsettop": "0" 75 | }, 76 | "bizstate": { 77 | "istop": 0, 78 | "isadvt": 0, 79 | "iscpc": 0, 80 | "cantop": 0, 81 | "canadvt": 0, 82 | "cancpc": 0, 83 | "mvip": 0 84 | }, 85 | "workplace": "北京", 86 | "years": "不限", 87 | "totalresume": 0, 88 | "shareCount": 0 89 | }, 90 | { 91 | "jobid": "34051057026994", 92 | "jobtitle": "测试员", 93 | "jobtype": 1, 94 | "looknum": 577, 95 | "updatetime": "2018-06-15", 96 | "unreadnum": 0, 97 | "jobstate": 1, 98 | "jobclass": 1, 99 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=34051057026994", 100 | "infostate": 1, 101 | "murl": "http://m.58.com/bj/tech/34051057026994x.shtml?v=1535531967201", 102 | "sal": "5000-8000元", 103 | "jz": 0, 104 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/34051057026994", 105 | "supportjz": 1, 106 | "shelvesstate": 1, 107 | "isRed": 0, 108 | "isCap": 0, 109 | "isShowCap": 1, 110 | "gjshelfstate": 1, 111 | "mvip": 0, 112 | "zcmGjPromotionTop": { 113 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=34051057026994", 114 | "isshowgjsettop": "1", 115 | "cangjsettop": "2" 116 | }, 117 | "bizstate": { 118 | "istop": 0, 119 | "isadvt": 0, 120 | "iscpc": 0, 121 | "cantop": 1, 122 | "canadvt": 0, 123 | "cancpc": 1, 124 | "mvip": 0 125 | }, 126 | "workplace": "北京", 127 | "years": "10年以上", 128 | "totalresume": 6, 129 | "shareCount": 0 130 | }, 131 | { 132 | "jobid": "29859112810921", 133 | "jobtitle": "服务员", 134 | "jobtype": 1, 135 | "looknum": 21, 136 | "updatetime": "2018-05-15", 137 | "unreadnum": 0, 138 | "jobstate": 0, 139 | "jobclass": 1, 140 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=29859112810921", 141 | "infostate": 0, 142 | "murl": "http://m.58.com/bj/zplvyoujiudian/29859112810921x.shtml?v=1535531967207", 143 | "sal": "3000-5000元", 144 | "jz": 0, 145 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/29859112810921", 146 | "supportjz": 0, 147 | "shelvesstate": 0, 148 | "isRed": 0, 149 | "isCap": 0, 150 | "isShowCap": 0, 151 | "gjshelfstate": 0, 152 | "mvip": 0, 153 | "zcmGjPromotionTop": { 154 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=29859112810921", 155 | "isshowgjsettop": "1", 156 | "cangjsettop": "0" 157 | }, 158 | "bizstate": { 159 | "istop": 0, 160 | "isadvt": 0, 161 | "iscpc": 0, 162 | "cantop": 0, 163 | "canadvt": 0, 164 | "cancpc": 0, 165 | "mvip": 0 166 | }, 167 | "workplace": "北京", 168 | "years": "不限", 169 | "totalresume": 1, 170 | "shareCount": 0 171 | }, 172 | { 173 | "jobid": "30147482837708", 174 | "jobtitle": "洗衣工", 175 | "jobtype": 1, 176 | "looknum": 91, 177 | "updatetime": "2017-10-09", 178 | "unreadnum": 0, 179 | "jobstate": 0, 180 | "jobclass": 1, 181 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=30147482837708", 182 | "infostate": 0, 183 | "murl": "http://m.58.com/bj/jiazhengbaojiexin/30147482837708x.shtml?v=1535531967225", 184 | "sal": "3000-5000元", 185 | "jz": 0, 186 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/30147482837708", 187 | "supportjz": 0, 188 | "shelvesstate": 0, 189 | "isRed": 0, 190 | "isCap": 0, 191 | "isShowCap": 0, 192 | "gjshelfstate": 0, 193 | "mvip": 0, 194 | "zcmGjPromotionTop": { 195 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=30147482837708", 196 | "isshowgjsettop": "1", 197 | "cangjsettop": "0" 198 | }, 199 | "bizstate": { 200 | "istop": 0, 201 | "isadvt": 0, 202 | "iscpc": 0, 203 | "cantop": 0, 204 | "canadvt": 0, 205 | "cancpc": 0, 206 | "mvip": 0 207 | }, 208 | "workplace": "北京", 209 | "years": "不限", 210 | "totalresume": 0, 211 | "shareCount": 0 212 | }, 213 | { 214 | "jobid": "30003190902469", 215 | "jobtitle": "服务员", 216 | "jobtype": 1, 217 | "looknum": 215, 218 | "updatetime": "2017-08-10", 219 | "unreadnum": 0, 220 | "jobstate": 3, 221 | "jobclass": 1, 222 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=30003190902469", 223 | "infostate": 5, 224 | "murl": "http://m.58.com/ab/zplvyoujiudian/30003190902469x.shtml?v=1535531967232", 225 | "sal": "面议", 226 | "jz": 0, 227 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/30003190902469", 228 | "supportjz": 0, 229 | "shelvesstate": 0, 230 | "isRed": 0, 231 | "isCap": 0, 232 | "isShowCap": 0, 233 | "gjshelfstate": 0, 234 | "mvip": 0, 235 | "zcmGjPromotionTop": { 236 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=30003190902469", 237 | "isshowgjsettop": "1", 238 | "cangjsettop": "0" 239 | }, 240 | "bizstate": { 241 | "istop": 0, 242 | "isadvt": 0, 243 | "iscpc": 0, 244 | "cantop": 0, 245 | "canadvt": 0, 246 | "cancpc": 0, 247 | "mvip": 0 248 | }, 249 | "workplace": "阿坝", 250 | "years": "3-5年", 251 | "totalresume": 9, 252 | "shareCount": 0 253 | }, 254 | { 255 | "jobid": "29439352378701", 256 | "jobtitle": "服务员", 257 | "jobtype": 1, 258 | "looknum": 0, 259 | "updatetime": "2017-03-20", 260 | "unreadnum": 0, 261 | "jobstate": 0, 262 | "jobclass": 1, 263 | "joburl": "https://zpbb.58.com/zcm/v3/views/position?infoid=29439352378701", 264 | "infostate": 0, 265 | "murl": "http://m.58.com/bj/zplvyoujiudian/29439352378701x.shtml?v=1535531967237", 266 | "sal": "面议", 267 | "jz": 0, 268 | "jzurl": "https://mcube.58.com/cube/m/pm/1/1010011/29439352378701", 269 | "supportjz": 0, 270 | "shelvesstate": 0, 271 | "isRed": 0, 272 | "isCap": 0, 273 | "isShowCap": 0, 274 | "gjshelfstate": 0, 275 | "mvip": 0, 276 | "zcmGjPromotionTop": { 277 | "gjsettopurl": "https://hrgnode.58.com/zcm/advertising?uid=34296832818699&infoid=29439352378701", 278 | "isshowgjsettop": "1", 279 | "cangjsettop": "0" 280 | }, 281 | "bizstate": { 282 | "istop": 0, 283 | "isadvt": 0, 284 | "iscpc": 0, 285 | "cantop": 0, 286 | "canadvt": 0, 287 | "cancpc": 0, 288 | "mvip": 0 289 | }, 290 | "workplace": "北京", 291 | "years": "不限", 292 | "totalresume": 0, 293 | "shareCount": 0 294 | } 295 | ], 296 | "competitive": 32 297 | }, 298 | "resultmsg": "获取成功" 299 | } -------------------------------------------------------------------------------- /app/src/main/java/com/dandan/jsonhandleview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dandan.jsonhandleview; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | 8 | import com.dandan.jsonhandleview.library.JsonViewLayout; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | private JsonViewLayout jsonViewLayout; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | jsonViewLayout = findViewById(R.id.json); 22 | new Thread(new Runnable() { 23 | @Override 24 | public void run() { 25 | InputStream is = null; 26 | try { 27 | is = getAssets().open("json.json"); 28 | int lenght = is.available(); 29 | byte[] buffer = new byte[lenght]; 30 | is.read(buffer); 31 | final String result = new String(buffer, "utf8"); 32 | is.close(); 33 | 34 | runOnUiThread(new Runnable() { 35 | @Override 36 | public void run() { 37 | jsonViewLayout.bindJson(result); 38 | } 39 | }); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | }).start(); 45 | } 46 | 47 | @Override 48 | public boolean onCreateOptionsMenu(Menu menu) { 49 | getMenuInflater().inflate(R.menu.menu_main, menu); 50 | return super.onCreateOptionsMenu(menu); 51 | } 52 | 53 | @Override 54 | public boolean onOptionsItemSelected(MenuItem item) { 55 | switch (item.getItemId()) { 56 | case R.id.action_expend: 57 | jsonViewLayout.expandAll(); 58 | break; 59 | case R.id.action_collapse: 60 | jsonViewLayout.collapseAll(); 61 | break; 62 | } 63 | return super.onOptionsItemSelected(item); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JsonHandleView 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | mavenCentral() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.1.3' 12 | 13 | // classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3" 14 | // classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' 15 | 16 | // NOTE: Do not place your application dependencies here; they belong 17 | // in the individual module build.gradle files 18 | } 19 | } 20 | 21 | allprojects { 22 | repositories { 23 | google() 24 | jcenter() 25 | mavenCentral() 26 | // maven(){ url 'https://dl.bintray.com/stven0king/maven'} 27 | } 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 30 16:24:03 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /jsonhandleview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /jsonhandleview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.novoda.bintray-release' 3 | 4 | buildscript { 5 | repositories { 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath 'com.novoda:bintray-release:+' 10 | } 11 | } 12 | 13 | android { 14 | compileSdkVersion 23 15 | 16 | 17 | 18 | defaultConfig { 19 | minSdkVersion 15 20 | targetSdkVersion 22 21 | versionCode 1 22 | versionName "1.0" 23 | 24 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 25 | 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | 35 | lintOptions { 36 | abortOnError false 37 | } 38 | 39 | } 40 | 41 | //如果你的项目里面有中文注释的话,必须将格式设置为UTF-8,不然会出现乱码 42 | tasks.withType(Javadoc){ 43 | options{ 44 | encoding 'UTF-8' 45 | charSet 'UTF-8' 46 | links "http://docs.oracle.com/javase/8/docs/api" 47 | } 48 | } 49 | 50 | publish { 51 | userOrg = 'stven0king' //bintray注册的用户名 52 | groupId = 'com.tzx.json' //compile引用时的第1部分groupId 53 | artifactId = 'jsonhandleview' //compile引用时的第2部分项目名 54 | publishVersion = '1.2.2' //compile引用时的第3部分版本号 55 | desc = 'Android json viewer, to convert json strings to a friendly readable format, it supports expend&collapsed json strings.' 56 | website = 'https://github.com/stven0king/JsonHandleView' 57 | } 58 | 59 | 60 | dependencies { 61 | implementation fileTree(dir: 'libs', include: ['*.jar']) 62 | 63 | implementation 'com.android.support:appcompat-v7:23.1.0' 64 | } 65 | -------------------------------------------------------------------------------- /jsonhandleview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/java/com/dandan/jsonhandleview/library/JsonView.java: -------------------------------------------------------------------------------- 1 | package com.dandan.jsonhandleview.library; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.support.annotation.Nullable; 6 | import android.util.AttributeSet; 7 | import android.util.TypedValue; 8 | import android.view.Gravity; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.ImageView; 13 | import android.widget.LinearLayout; 14 | import android.widget.TextView; 15 | 16 | /** 17 | * Created by Tanzhenxing 18 | * Date: 2018/8/30 下午2:13 19 | * Description: 每一条JSON的key-value展示 20 | */ 21 | public class JsonView extends LinearLayout{ 22 | private ImageView imageview; 23 | private TextView keyTV, valueTV, commandTV; 24 | private View contentView; 25 | private Context mContext; 26 | public JsonView(Context context) { 27 | super(context); 28 | this.mContext = context; 29 | initView(); 30 | } 31 | 32 | public JsonView(Context context, @Nullable AttributeSet attrs) { 33 | super(context, attrs); 34 | this.mContext = context; 35 | initView(); 36 | } 37 | 38 | public JsonView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 39 | super(context, attrs, defStyleAttr); 40 | this.mContext = context; 41 | initView(); 42 | } 43 | 44 | private void initView() { 45 | setOrientation(VERTICAL); 46 | LayoutInflater.from(mContext).inflate(R.layout.item_view_jsonview_layout, this, true); 47 | imageview = (ImageView) findViewById(R.id.icon); 48 | keyTV = (TextView) findViewById(R.id.key); 49 | valueTV = (TextView) findViewById(R.id.value); 50 | commandTV = (TextView) findViewById(R.id.command); 51 | contentView = findViewById(R.id.content); 52 | contentView.setBackgroundColor(Color.TRANSPARENT); 53 | imageview.setVisibility(GONE); 54 | keyTV.setVisibility(GONE); 55 | valueTV.setVisibility(GONE); 56 | setTextSize(JsonViewLayout.TEXT_SIZE_DP); 57 | } 58 | 59 | public void setTextSize(float textSizeDp) { 60 | JsonViewLayout.TEXT_SIZE_DP = (int) textSizeDp; 61 | keyTV.setTextSize(JsonViewLayout.TEXT_SIZE_DP); 62 | valueTV.setTextSize(JsonViewLayout.TEXT_SIZE_DP); 63 | commandTV.setTextSize(JsonViewLayout.TEXT_SIZE_DP); 64 | int textSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, JsonViewLayout.TEXT_SIZE_DP, getResources().getDisplayMetrics()); 65 | LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageview.getLayoutParams(); 66 | layoutParams.height = textSize; 67 | layoutParams.width = textSize; 68 | int rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, JsonViewLayout.TEXT_SIZE_DP / 4, getResources().getDisplayMetrics()); 69 | layoutParams.rightMargin = rightMargin; 70 | layoutParams.gravity = Gravity.CENTER_VERTICAL; 71 | imageview.setLayoutParams(layoutParams); 72 | } 73 | 74 | public void setCommand(CharSequence sequence) { 75 | commandTV.setText(sequence); 76 | } 77 | 78 | 79 | public void hideIcon() { 80 | imageview.setVisibility(GONE); 81 | } 82 | 83 | public void showIcon(boolean canExpand) { 84 | imageview.setVisibility(VISIBLE); 85 | imageview.setImageResource(canExpand ? R.drawable.jsonview_item_expand : R.drawable.jsonview_item_collapse); 86 | } 87 | 88 | public void hideValue() { 89 | valueTV.setVisibility(GONE); 90 | } 91 | 92 | public void showValue(CharSequence s) { 93 | valueTV.setVisibility(VISIBLE); 94 | valueTV.setText(s); 95 | valueTV.setBackgroundColor(Color.TRANSPARENT); 96 | } 97 | 98 | public void showArrayLength(int resId) { 99 | valueTV.setBackgroundResource(resId); 100 | } 101 | 102 | public void showKey(CharSequence s) { 103 | keyTV.setVisibility(VISIBLE); 104 | keyTV.setText(s); 105 | } 106 | 107 | public void setIconClickListener(View.OnClickListener listener) { 108 | imageview.setOnClickListener(listener); 109 | } 110 | 111 | public void expand() { 112 | imageview.setTag(false); 113 | imageview.callOnClick(); 114 | } 115 | 116 | public void collapse() { 117 | imageview.setTag(true); 118 | imageview.callOnClick(); 119 | } 120 | 121 | public void addViewNoInvalidate(View child) { 122 | ViewGroup.LayoutParams params = child.getLayoutParams(); 123 | if (params == null) { 124 | params = generateDefaultLayoutParams(); 125 | if (params == null) { 126 | throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null"); 127 | } 128 | } 129 | addViewInLayout(child, -1, params); 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/java/com/dandan/jsonhandleview/library/JsonViewLayout.java: -------------------------------------------------------------------------------- 1 | package com.dandan.jsonhandleview.library; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.text.SpannableStringBuilder; 6 | import android.text.Spanned; 7 | import android.text.style.ForegroundColorSpan; 8 | import android.util.AttributeSet; 9 | import android.util.Log; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.FrameLayout; 14 | import android.widget.HorizontalScrollView; 15 | import android.widget.LinearLayout; 16 | import android.widget.ScrollView; 17 | 18 | import org.json.JSONArray; 19 | import org.json.JSONException; 20 | import org.json.JSONObject; 21 | import org.json.JSONTokener; 22 | 23 | /** 24 | * Created by Tanzhenxing 25 | * Date: 2018/8/30 下午2:14 26 | * Description: JSON的View容器 27 | */ 28 | public class JsonViewLayout extends ScrollView { 29 | 30 | private int ITEM_KEY_COLOR = 0xFF61a731; 31 | private int OBJECT_KEY_COLOR = 0xFF333333; 32 | private int TEXT_COLOR = 0xFFEE6F43; 33 | private int NUMBER_COLOR = 0xFFC353F6; 34 | private int ARRAY_LENGTH_COLOR = 0xFFFFFFFF; 35 | private int BOOLEAN_COLOR = 0xFF4098C7; 36 | private int NULL_COLOR = 0xFFBCBA58; 37 | 38 | public static float TEXT_SIZE_DP = 18; 39 | 40 | private int TEXT_SIZE_DP_MAX = 32; 41 | private int TEXT_SIZE_DP_MIN = 12; 42 | 43 | private int ARRAY_LENGTH_BACKGROUND = R.drawable.jsonview_select_bg; 44 | 45 | private Context mContext; 46 | private JSONObject mJSONObject; 47 | private JSONArray mJSONArray; 48 | 49 | private LinearLayout contentView; 50 | 51 | private HorizontalScrollView horizontalScrollView; 52 | 53 | public JsonViewLayout(Context context) { 54 | super(context); 55 | initView(context); 56 | 57 | } 58 | 59 | public JsonViewLayout(Context context, @Nullable AttributeSet attrs) { 60 | super(context, attrs); 61 | initView(context); 62 | } 63 | 64 | public JsonViewLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 65 | super(context, attrs, defStyleAttr); 66 | initView(context); 67 | } 68 | 69 | private void initView(Context context) { 70 | this.mContext = context; 71 | contentView = new LinearLayout(mContext); 72 | FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 73 | contentView.setLayoutParams(layoutParams); 74 | contentView.setOrientation(LinearLayout.VERTICAL); 75 | horizontalScrollView = new HorizontalScrollView(mContext); 76 | horizontalScrollView.setLayoutParams(layoutParams); 77 | horizontalScrollView.setPadding(12, 12, 12, 0); 78 | horizontalScrollView.addView(contentView); 79 | this.addView(horizontalScrollView); 80 | } 81 | 82 | public void bindJson(String jsonStr) { 83 | if (canBindData()) { 84 | throw new IllegalArgumentException("JsonViweLayout can not bind again."); 85 | } 86 | Object object = null; 87 | try { 88 | object = new JSONTokener(jsonStr).nextValue(); 89 | } catch (JSONException e) { 90 | e.printStackTrace(); 91 | } 92 | if (object != null && object instanceof JSONObject) { 93 | mJSONObject = (JSONObject) object; 94 | } else if (object != null && object instanceof JSONArray) { 95 | mJSONArray = (JSONArray) object; 96 | } else { 97 | throw new IllegalArgumentException("jsonStr is illegal."); 98 | } 99 | createView(); 100 | } 101 | 102 | public void bindJson(JSONObject mJSONObject) { 103 | if (canBindData()) { 104 | throw new IllegalArgumentException("JsonViweLayout can not bind again."); 105 | } 106 | this.mJSONObject = mJSONObject; 107 | if (mJSONObject == null) { 108 | throw new IllegalArgumentException("jsonObject can not be null."); 109 | } 110 | createView(); 111 | } 112 | 113 | public void bindJson(JSONArray mJSONArray) { 114 | if (canBindData()) { 115 | throw new IllegalArgumentException("JsonViweLayout can not bind again."); 116 | } 117 | this.mJSONArray = mJSONArray; 118 | if (mJSONArray == null) { 119 | throw new IllegalArgumentException("jsonArray can not be null."); 120 | } 121 | createView(); 122 | } 123 | 124 | private boolean canBindData() { 125 | return null != mJSONObject || null != mJSONArray; 126 | } 127 | 128 | private void createView() { 129 | JsonView jsonView = new JsonView(mContext); 130 | jsonView.showIcon(true); 131 | jsonView.hideValue(); 132 | SpannableStringBuilder keyBuilder = new SpannableStringBuilder(); 133 | keyBuilder.append("JSON"); 134 | keyBuilder.setSpan(new ForegroundColorSpan(OBJECT_KEY_COLOR), 0, keyBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 135 | jsonView.showKey(keyBuilder); 136 | Object value = null != mJSONObject ? mJSONObject : mJSONArray; 137 | jsonView.setIconClickListener(new JsonViewOnClickListener(value, jsonView, 0)); 138 | contentView.addView(jsonView); 139 | } 140 | 141 | 142 | private void handleJsonObject(String key, Object value, JsonView itemView, int hierarchy) { 143 | SpannableStringBuilder keyBuilder = new SpannableStringBuilder(); 144 | SpannableStringBuilder valueBuilder = new SpannableStringBuilder(); 145 | itemView.hideIcon(); 146 | if (value instanceof JSONObject) { 147 | itemView.showIcon(true); 148 | itemView.setIconClickListener(new JsonViewOnClickListener(value, itemView, hierarchy + 1)); 149 | keyBuilder.append(key); 150 | keyBuilder.setSpan(new ForegroundColorSpan(OBJECT_KEY_COLOR), 0, keyBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 151 | itemView.setCommand(getHierarchyStr(hierarchy + 1)); 152 | } else { 153 | keyBuilder.append("\"").append(key).append("\"").append(":"); 154 | keyBuilder.setSpan(new ForegroundColorSpan(ITEM_KEY_COLOR), 0, keyBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 155 | if (value instanceof JSONArray) { 156 | itemView.showIcon(true); 157 | itemView.setIconClickListener(new JsonViewOnClickListener(value, itemView, hierarchy + 1)); 158 | itemView.setCommand(getHierarchyStr(hierarchy)); 159 | valueBuilder.append(" " + ((JSONArray) value).length() + " "); 160 | valueBuilder.setSpan(new ForegroundColorSpan(ARRAY_LENGTH_COLOR), 0, valueBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 161 | itemView.showValue(valueBuilder); 162 | itemView.showArrayLength(ARRAY_LENGTH_BACKGROUND); 163 | } else { 164 | itemView.hideIcon(); 165 | valueBuilder.append(value.toString()); 166 | int valueColor; 167 | if (value instanceof String) { 168 | valueColor = TEXT_COLOR; 169 | } else if (value instanceof Boolean) { 170 | valueColor = BOOLEAN_COLOR; 171 | } else if (value instanceof Number){ 172 | valueColor = NUMBER_COLOR; 173 | } else { 174 | valueColor = NULL_COLOR; 175 | } 176 | valueBuilder.setSpan(new ForegroundColorSpan(valueColor), 0, valueBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 177 | itemView.showValue(valueBuilder); 178 | itemView.setCommand(getHierarchyStr(hierarchy + 1)); 179 | } 180 | } 181 | itemView.showKey(keyBuilder); 182 | } 183 | 184 | 185 | class JsonViewOnClickListener implements View.OnClickListener { 186 | private Object value; 187 | private JsonView itemView; 188 | private int hierarchy; 189 | 190 | private boolean isexpand = true; 191 | private boolean isJsonArray; 192 | 193 | public JsonViewOnClickListener(Object value, JsonView itemView, int hierarchy) { 194 | this.value = value; 195 | this.itemView = itemView; 196 | this.hierarchy = hierarchy; 197 | this.isJsonArray = value != null && value instanceof JSONArray; 198 | } 199 | 200 | @Override 201 | public void onClick(View v) { 202 | Object obj = v.getTag(); 203 | if (obj != null && obj instanceof Boolean) { 204 | this.isexpand = (boolean) obj; 205 | v.setTag(null); 206 | } 207 | if (itemView.getChildCount() == 1) { 208 | JSONArray array = isJsonArray ? (JSONArray) value : ((JSONObject) value).names(); 209 | if (null != array) { 210 | this.isexpand = false; 211 | if (!isJsonArray && array.length() == 1 && "nameValuePairs".equals(array.opt(0).toString())) { 212 | Object nameValuePairs = ((JSONObject) value).opt("nameValuePairs"); 213 | if (null != nameValuePairs) { 214 | value = nameValuePairs; 215 | isJsonArray = value instanceof JSONArray; 216 | array = isJsonArray ? (JSONArray) value : ((JSONObject) value).names(); 217 | } 218 | } 219 | for (int i = 0; array != null && i < array.length(); i++) { 220 | JsonView childItemView = new JsonView(itemView.getContext()); 221 | Object childValue = array.opt(i); 222 | if (isJsonArray) { 223 | handleJsonObject(String.valueOf(i), childValue, childItemView, hierarchy); 224 | } else { 225 | handleJsonObject((String) childValue, ((JSONObject) value).opt((String) childValue), childItemView, hierarchy); 226 | } 227 | itemView.addViewNoInvalidate(childItemView); 228 | } 229 | } else { 230 | this.isexpand = !isexpand; 231 | } 232 | itemView.showIcon(isexpand); 233 | itemView.requestLayout(); 234 | itemView.invalidate(); 235 | } else { 236 | isexpand = !isexpand; 237 | itemView.showIcon(isexpand); 238 | for (int i = 1; i < itemView.getChildCount(); i++) { 239 | itemView.getChildAt(i).setVisibility(!isexpand ? View.VISIBLE : View.GONE); 240 | } 241 | } 242 | } 243 | } 244 | 245 | public void setTextSize(float sizeDP) { 246 | if (sizeDP < TEXT_SIZE_DP_MIN) { 247 | sizeDP = TEXT_SIZE_DP_MIN; 248 | } else if (sizeDP > TEXT_SIZE_DP_MAX) { 249 | sizeDP = TEXT_SIZE_DP_MAX; 250 | } 251 | if (TEXT_SIZE_DP != sizeDP) { 252 | TEXT_SIZE_DP = sizeDP; 253 | updateAll(sizeDP); 254 | } 255 | } 256 | 257 | public void updateAll(float textSize) { 258 | int count = this.getChildCount(); 259 | for (int i = 0; i < count; i++) { 260 | View view = contentView.getChildAt(i); 261 | loop(view, textSize); 262 | } 263 | } 264 | 265 | private void loop(View view, float textSize) { 266 | if (view instanceof JsonView) { 267 | JsonView group = (JsonView) view; 268 | group.setTextSize(textSize); 269 | int childCount = group.getChildCount(); 270 | for (int i = 0; i < childCount; i++) { 271 | View view1 = group.getChildAt(i); 272 | loop(view1, textSize); 273 | } 274 | } 275 | } 276 | 277 | int mode; 278 | float oldDist; 279 | 280 | private void zoom(float f) { 281 | Log.d("tanzhenxing", "zoom = " + f); 282 | setTextSize(TEXT_SIZE_DP * (f / 100 + 1)); 283 | } 284 | 285 | private float spacing(MotionEvent event) { 286 | float x = event.getX(0) - event.getX(1); 287 | float y = event.getY(0) - event.getY(1); 288 | return (float) Math.sqrt(x * x + y * y); 289 | } 290 | 291 | 292 | @Override 293 | public boolean dispatchTouchEvent(MotionEvent event) { 294 | boolean intercept = false; 295 | switch (event.getAction() & event.getActionMasked()) { 296 | case MotionEvent.ACTION_DOWN: 297 | mode = 1; 298 | break; 299 | case MotionEvent.ACTION_UP: 300 | mode = 0; 301 | break; 302 | case MotionEvent.ACTION_POINTER_UP: 303 | intercept = true; 304 | mode -= 1; 305 | break; 306 | case MotionEvent.ACTION_POINTER_DOWN: 307 | intercept = false; 308 | oldDist = spacing(event); 309 | mode += 1; 310 | break; 311 | 312 | case MotionEvent.ACTION_MOVE: 313 | if (mode >= 2) { 314 | float newDist = spacing(event); 315 | if (Math.abs(newDist - oldDist) > 3f) { 316 | zoom(newDist - oldDist); 317 | oldDist = newDist; 318 | } 319 | } 320 | break; 321 | } 322 | return intercept ? intercept : super.dispatchTouchEvent(event); 323 | } 324 | 325 | public void setKeyColor(int color) { 326 | ITEM_KEY_COLOR = color; 327 | } 328 | 329 | public void setObjectKeyColor(int color) { 330 | OBJECT_KEY_COLOR = color; 331 | } 332 | 333 | public void setValueTextColor(int color) { 334 | TEXT_COLOR = color; 335 | } 336 | 337 | public void setValueNumberColor(int color) { 338 | NUMBER_COLOR = color; 339 | } 340 | 341 | public void setValueBooleanColor(int color) { 342 | BOOLEAN_COLOR = color; 343 | } 344 | 345 | public void setValueNullColor(int color) { 346 | NUMBER_COLOR = color; 347 | } 348 | 349 | public void setArrayLengthColor(int color) { 350 | ARRAY_LENGTH_COLOR = color; 351 | } 352 | 353 | private String getHierarchyStr(int hierarchy) { 354 | StringBuilder levelStr = new StringBuilder(); 355 | for (int levelI = 0; levelI < hierarchy; levelI++) { 356 | levelStr.append(" "); 357 | } 358 | return levelStr.toString(); 359 | } 360 | 361 | public void expandAll() { 362 | if (contentView != null) { 363 | clickAllView(contentView, false); 364 | } 365 | } 366 | 367 | public void collapseAll() { 368 | if (contentView != null) { 369 | clickAllView(contentView, true); 370 | } 371 | } 372 | 373 | private void clickAllView(ViewGroup viewGroup, boolean collapse) { 374 | if (viewGroup instanceof JsonView) { 375 | JsonView jsonView = (JsonView) viewGroup; 376 | operationJsonView(jsonView, collapse); 377 | } 378 | for (int i = 0; i < viewGroup.getChildCount(); i++) { 379 | View view = viewGroup.getChildAt(i); 380 | if (viewGroup instanceof JsonView) { 381 | JsonView jsonView = (JsonView) viewGroup; 382 | operationJsonView(jsonView, collapse); 383 | } 384 | if (view instanceof ViewGroup) { 385 | clickAllView((ViewGroup) view, collapse); 386 | } 387 | } 388 | } 389 | 390 | private void operationJsonView(JsonView jsonView, boolean collapse) { 391 | if (jsonView != null) { 392 | if (collapse) { 393 | jsonView.expand(); 394 | } else { 395 | jsonView.collapse(); 396 | } 397 | } 398 | } 399 | } 400 | 401 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/res/drawable-xxhdpi/jsonview_item_collapse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 13 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/res/drawable-xxhdpi/jsonview_item_expand.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 26 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/res/drawable-xxhdpi/jsonview_select_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/res/layout/item_view_jsonview_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 26 | 27 | 33 | 34 | 41 | 42 | 50 | 51 | -------------------------------------------------------------------------------- /jsonhandleview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JsonHandleView 3 | 4 | -------------------------------------------------------------------------------- /screenshots/json-expand.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/screenshots/json-expand.gif -------------------------------------------------------------------------------- /screenshots/json-handle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/screenshots/json-handle.gif -------------------------------------------------------------------------------- /screenshots/json-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stven0king/JsonHandleView/a21ad9f0957adc6f8a586abb8bc842fdcec22930/screenshots/json-handle.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':jsonhandleview' 2 | --------------------------------------------------------------------------------