├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── LICENSE ├── README.md ├── README_zh.md ├── UETool_Introduction.pdf ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── debug │ ├── java │ │ └── me │ │ │ └── ele │ │ │ └── uetool │ │ │ └── sample │ │ │ ├── CustomAttribution.java │ │ │ └── XmlLancet.java │ └── res │ │ └── values │ │ └── ids.xml │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── ele │ │ │ └── uetool │ │ │ └── sample │ │ │ ├── AppContext.java │ │ │ ├── CustomDialog.java │ │ │ ├── CustomLayout.java │ │ │ ├── CustomView.java │ │ │ ├── FilterOutView.java │ │ │ ├── FragmentSampleActivity.kt │ │ │ ├── MainActivity.java │ │ │ ├── SecondActivity.java │ │ │ ├── VerticalImageSpan.java │ │ │ └── ui │ │ │ ├── fragmentsample │ │ │ ├── FragmentSampleFragment.kt │ │ │ ├── FragmentSampleFragment2.kt │ │ │ └── FragmentSampleViewModel.kt │ │ │ └── recyclerviewsample │ │ │ └── RecyclerViewActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxhdpi │ │ ├── ic_down_vote.png │ │ ├── ic_food_new.png │ │ ├── ic_placeholder.png │ │ ├── ic_tip.9.png │ │ └── ic_up_vote.png │ │ ├── drawable │ │ ├── gradient_background.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_recycler_view.xml │ │ ├── activity_second.xml │ │ ├── custom_layout.xml │ │ ├── dialog_layout.xml │ │ ├── fragment_sample_activity.xml │ │ ├── fragment_sample_fragment.xml │ │ └── layout_simple_textview.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 │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── release │ └── java │ └── me.ele.uetool.sample │ └── CustomAttribution.java ├── art ├── move_view.gif ├── relative_position.gif ├── show_gridding.png ├── show_image_uri.gif └── uet_banner.jpeg ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── uetool-base ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── me │ └── ele │ └── uetool │ └── base │ ├── Application.java │ ├── DimenUtil.java │ ├── Element.java │ ├── IAttrs.java │ ├── ItemArrayList.java │ ├── ItemViewBinder.java │ ├── ReflectionP.java │ └── item │ ├── AddMinusEditItem.java │ ├── BitmapItem.java │ ├── BriefDescItem.java │ ├── EditTextItem.java │ ├── ElementItem.java │ ├── Item.java │ ├── SwitchItem.java │ ├── TextItem.java │ └── TitleItem.java ├── uetool-fresco ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── me │ └── ele │ └── uetool │ └── fresco │ └── UETFresco.java ├── uetool-no-op ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── me │ └── ele │ └── uetool │ ├── UETool.java │ └── base │ ├── ItemViewBinder.java │ └── item │ └── Item.java ├── uetool.jks └── uetool ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── me │ └── ele │ └── uetool │ ├── AttrsDialog.java │ ├── BoardTextView.java │ ├── CollectViewsLayout.java │ ├── EditAttrLayout.java │ ├── FragmentListTreeDialog.java │ ├── GriddingLayout.java │ ├── Provider.java │ ├── RegionView.java │ ├── RelativePositionLayout.java │ ├── TransparentActivity.java │ ├── UETCore.java │ ├── UETMenu.java │ ├── UETSubMenu.java │ ├── UETool.java │ ├── Util.java │ └── attrdialog │ ├── AttrsDialogItemViewBinder.java │ ├── AttrsDialogMultiTypePool.java │ └── binder │ ├── AddMinusEditTextItemBinder.java │ ├── BitmapItemBinder.java │ ├── BriefDescItemBinder.java │ ├── EditTextItemBinder.java │ ├── SwitchItemBinder.java │ ├── TextItemBinder.java │ └── TitleItemBinder.java └── res ├── drawable-xxhdpi ├── uet_add.png ├── uet_add_pressed.png ├── uet_close.png ├── uet_edit_attr.png ├── uet_menu.png ├── uet_minus.png ├── uet_minus_pressed.png ├── uet_relative_position.png ├── uet_scalpel.png ├── uet_show_gridding.png ├── uet_sub_menu_bg.9.png └── uet_tree_arrow.png ├── drawable ├── uet_selector_add.xml ├── uet_selector_brief_desc.xml └── uet_selector_minus.xml ├── layout ├── uet_activity_transparent.xml ├── uet_cell_add_minus_edit.xml ├── uet_cell_bitmap_info.xml ├── uet_cell_brief_view_desc.xml ├── uet_cell_edit_text.xml ├── uet_cell_switch.xml ├── uet_cell_text.xml ├── uet_cell_title.xml ├── uet_cell_tree.xml ├── uet_dialog_attrs.xml ├── uet_dialog_fragment_list_tree.xml ├── uet_menu_layout.xml └── uet_sub_menu_layout.xml ├── values-en └── strings.xml ├── values-zh └── strings.xml └── values ├── dimens.xml ├── strings.xml └── values.xml /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Issue Description 2 | 3 | #### Description 4 | 5 | [Tell us about the issue] 6 | 7 | #### Reproduce 8 | 9 | [The steps to reproduce this issue. What are the parameters, where did you put your code, etc.] 10 | 11 | #### Other Comment 12 | 13 | [Add anything else here] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 UETool. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UETool [![GitHub release](https://img.shields.io/github/release/eleme/UETool.svg?style=social)](https://github.com/eleme/UETool/releases) [![platform](https://img.shields.io/badge/platform-android-brightgreen.svg)](https://developer.android.com/index.html) [![license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/eleme/UETool/blob/master/LICENSE) 2 | ====== 3 | 4 | ![](https://github.com/eleme/UETool/blob/master/art/uet_banner.jpeg) 5 | 6 | ## INTRODUCTION 7 | 8 | [中文版](https://github.com/eleme/UETool/blob/master/README_zh.md) 9 | 10 | UETool is a debug tool for anyone who needs to show and edit the attributes of user interface views on mobile devices. It works on Activity/Fragment/Dialog/PopupWindow or any other view. 11 | 12 | Presently, UETool provides the following functionalities: 13 | 14 | - Move any view on the screen (selecting view repeatedly will select its parent's view) 15 | - Show/edit normal view's attributes such as TextView's text, textSize, textColor etc. 16 | - Show two view's relative positions 17 | - Show grid for checking view alignment 18 | - Support Android P 19 | - Show view's current Fragment 20 | - Show activity's Fragment tree 21 | - Show view's view holder name if it exist 22 | - Easily customize any view's attributes you want simply, such as business parameters 23 | 24 | - If you are using Fresco's DraweeView, UETool shows more properties like ImageURI, PlaceHolderImage, CornerRadius etc. 25 | - If the view selected by UETool isn’t what you want, you can check ValidViews to choose which target view you want 26 | 27 | ## UETool's Effects: 28 | 29 |
30 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 |
40 | 41 | 42 | ## ATTRIBUTE LIST 43 | 44 | | Attribute | Value Sample | Editable | 45 | | --- | --- | --- | 46 | | Move | if you checked it, you can move view easily | | 47 | | ValidViews | sometimes target view which UETool offered isn’t you want, you can check it and choose which you want | | 48 | | Class | android.widget.LinearLayout | | 49 | | Id | 0x7f0d009c | | 50 | | ResName | btn | | 51 | | Clickble | TRUE | | 52 | | Focoused | FALSE | | 53 | | Width(dp) | 107 | YES | 54 | | Height(dp) | 19 | YES | 55 | | Alpha | 1.0 | | 56 | | PaddingLeft(dp) | 10 | YES | 57 | | PaddingRight(dp) | 10 | YES | 58 | | PaddingTop(dp) | 10 | YES | 59 | | PaddingBottom(dp) | 10 | YES | 60 | | Background | #90000000
#FF8F8F8F -> #FF688FDB
[PICTURE] 300px*300px | | 61 | | **TextView** | | | 62 | | Text | Hello World | YES | 63 | | TextSize(sp) | 14 | YES | 64 | | TextColor | #DE000000 | YES | 65 | | IsBold | TRUE | YES | 66 | | SpanBitmap | [PICTURE] 72px*39px | | 67 | | DrawableLeft | [PICTURE] 51px*51px | | 68 | | DrawableRight | [PICTURE] 36px*36px | | 69 | | DrawableTop | [PICTURE] 36px*36px | | 70 | | DrawableBottom | [PICTURE] 36px*36px | | 71 | | **ImageView** | | | 72 | | Bitmap | [PICTURE] 144px*144px | | 73 | | ScaleType | CENTER_CROP | | 74 | | **DraweeView** | | | 75 | | CornerRadius | 2dp | | 76 | | ImageURI | https://avatars2.githubusercontent.com/u/1201438?s=200&v=4 | | 77 | | ActualScaleType | CENTER_CROP | | 78 | | IsSupportAnimation | TRUE | | 79 | | PlaceHolderImage | [PICTURE] 300px*300px | | 80 | | | | | 81 | 82 | 83 | ## HOW TO USE 84 | 85 | ### Installation 86 | 87 | ```gradle 88 | allprojects { 89 | repositories { 90 | ... 91 | maven { url 'https://jitpack.io' } 92 | } 93 | } 94 | 95 | dependencies { 96 | debugImplementation 'com.github.eleme.UETool:uetool:1.3.4' 97 | debugImplementation 'com.github.eleme.UETool:uetool-base:1.3.4' 98 | releaseImplementation 'com.github.eleme.UETool:uetool-no-op:1.3.4' 99 | 100 | // if you want to show more attrs about Fresco's DraweeView 101 | debugImplementation 'com.github.eleme.UETool:uetool-fresco:1.3.4' 102 | } 103 | ``` 104 | 105 | ### Usage 106 | 107 | #### Show floating window 108 | 109 | ```java 110 | UETool.showUETMenu(); 111 | 112 | UETool.showUETMenu(int y); 113 | ``` 114 | 115 | #### Dismiss floating window 116 | 117 | ```java 118 | UETool.dismissUETMenu(); 119 | ``` 120 | 121 | #### Filter out unwanted views from selection 122 | 123 | ```java 124 | UETool.putFilterClass(Class viewClazz); 125 | 126 | UETool.putFilterClass(String viewClassName); 127 | ``` 128 | 129 | #### Customize your view 130 | 131 | ```java 132 | 133 | // step 1, implement IAttrs 134 | 135 | public class UETFresco implements IAttrs { 136 | @Override public List getAttrs(Element element) { 137 | 138 | } 139 | } 140 | 141 | // step 2, put in UETool 142 | 143 | UETool.putAttrsProviderClass(Class customizeClazz); 144 | 145 | UETool.putAttrsProviderClass(String customizeClassName); 146 | 147 | ``` 148 | 149 | ## License 150 | 151 | [MIT](http://opensource.org/licenses/MIT) 152 | 153 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | UETool [![GitHub release](https://img.shields.io/github/release/eleme/UETool.svg?style=social)](https://github.com/eleme/UETool/releases) [![platform](https://img.shields.io/badge/platform-android-brightgreen.svg)](https://developer.android.com/index.html) [![license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/eleme/UETool/blob/master/LICENSE) 2 | ====== 3 | 4 | ![](https://github.com/eleme/UETool/blob/master/art/uet_banner.jpeg) 5 | 6 | ## 介绍 7 | 8 | UETool 是一个各方人员(设计师、程序员、测试)都可以使用的调试工具。它可以作用于任何显示在屏幕上的 view,比如 Activity/Fragment/Dialog/PopupWindow 等等。 9 | 10 | 目前 UETool 提供以下功能: 11 | 12 | - 移动屏幕上的任意 view,如果重复选中一个 view,将会选中其父 view 13 | - 查看/修改常用控件的属性,比如修改 TextView 的文本内容、文本大小、文本颜色等等 14 | - 如果你的项目里正在使用 Fresco 的 DraweeView 来呈现图片,那么 UETool 将会提供更多的属性比如图片 URI、默认占位图、圆角大小等等 15 | - 你可以很轻松的定制任何 view 的属性,比如你想查看一些额外的业务参数 16 | - 有的时候 UETool 为你选中的 view 并不是你想要的,你可以选择打开 ValidView,然后选中你需要的 View 17 | - 显示两个 view 的相对位置关系 18 | - 显示网格栅栏,方便查看控件是否对齐 19 | - 支持 Android P 20 | - 支持显示当前控件所在的 Fragment 21 | - 显示 Activity 的 Fragment 树 22 | - 如果 view 在 RecyclerView 中,显示这个 view 所在的 ViewHolder 类名 23 | 24 | ## 效果 25 | 26 |
27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 |
37 | 38 | ## 属性列表 39 | 40 | | Attribute | Value Sample | Editable | 41 | | --- | --- | --- | 42 | | Move | if you checked it, you can move view easily | | 43 | | ValidViews | sometimes target view which UETool offered isn’t you want, you can check it and choose which you want | | 44 | | Class | android.widget.LinearLayout | | 45 | | Id | 0x7f0d009c | | 46 | | ResName | btn | | 47 | | Clickble | TRUE | | 48 | | Focoused | FALSE | | 49 | | Width(dp) | 107 | YES | 50 | | Height(dp) | 19 | YES | 51 | | Alpha | 1.0 | | 52 | | PaddingLeft(dp) | 10 | YES | 53 | | PaddingRight(dp) | 10 | YES | 54 | | PaddingTop(dp) | 10 | YES | 55 | | PaddingBottom(dp) | 10 | YES | 56 | | Background | #90000000
#FF8F8F8F -> #FF688FDB
[PICTURE] 300px*300px | | 57 | | **TextView** | | | 58 | | Text | Hello World | YES | 59 | | TextSize(sp) | 14 | YES | 60 | | TextColor | #DE000000 | YES | 61 | | IsBold | TRUE | YES | 62 | | SpanBitmap | [PICTURE] 72px*39px | | 63 | | DrawableLeft | [PICTURE] 51px*51px | | 64 | | DrawableRight | [PICTURE] 36px*36px | | 65 | | DrawableTop | [PICTURE] 36px*36px | | 66 | | DrawableBottom | [PICTURE] 36px*36px | | 67 | | **ImageView** | | | 68 | | Bitmap | [PICTURE] 144px*144px | | 69 | | ScaleType | CENTER_CROP | | 70 | | **DraweeView** | | | 71 | | CornerRadius | 2dp | | 72 | | ImageURI | https://avatars2.githubusercontent.com/u/1201438?s=200&v=4 | | 73 | | ActualScaleType | CENTER_CROP | | 74 | | IsSupportAnimation | TRUE | | 75 | | PlaceHolderImage | [PICTURE] 300px*300px | | 76 | | | | | 77 | 78 | 79 | ## 如何使用 80 | 81 | ### 安装依赖 82 | 83 | ```gradle 84 | allprojects { 85 | repositories { 86 | ... 87 | maven { url 'https://jitpack.io' } 88 | } 89 | } 90 | 91 | dependencies { 92 | debugImplementation 'com.github.eleme.UETool:uetool:1.3.4' 93 | debugImplementation 'com.github.eleme.UETool:uetool-base:1.3.4' 94 | releaseImplementation 'com.github.eleme.UETool:uetool-no-op:1.3.4' 95 | 96 | // if you want to show more attrs about Fresco's DraweeView 97 | debugImplementation 'com.github.eleme.UETool:uetool-fresco:1.3.4' 98 | } 99 | ``` 100 | 101 | ### 使用 102 | 103 | #### 打开悬浮窗 104 | 105 | ```java 106 | UETool.showUETMenu(); 107 | 108 | UETool.showUETMenu(int y); 109 | ``` 110 | 111 | #### 关掉悬浮窗 112 | 113 | ```java 114 | UETool.dismissUETMenu(); 115 | ``` 116 | 117 | #### 过滤掉你不需要选中的 View 118 | 119 | ```java 120 | UETool.putFilterClass(Class viewClazz); 121 | 122 | UETool.putFilterClass(String viewClassName); 123 | ``` 124 | 125 | #### 自定义实现你的 View 的属性 126 | 127 | ```java 128 | 129 | // step 1, implements IAttrs 130 | 131 | public class UETFresco implements IAttrs { 132 | @Override public List getAttrs(Element element) { 133 | 134 | } 135 | } 136 | 137 | // step 2, put in UETool 138 | 139 | UETool.putAttrsProviderClass(Class customizeClazz); 140 | 141 | UETool.putAttrsProviderClass(String customizeClassName); 142 | 143 | ``` 144 | 145 | ## License 146 | 147 | [MIT](http://opensource.org/licenses/MIT) 148 | 149 | -------------------------------------------------------------------------------- /UETool_Introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/UETool_Introduction.pdf -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'me.ele.lancet' 5 | 6 | android { 7 | compileSdkVersion versions.compileSdk 8 | 9 | signingConfigs { 10 | release { 11 | storeFile file("../uetool.jks") 12 | keyAlias 'uetool' 13 | keyPassword 'uetool' 14 | storePassword 'uetool' 15 | } 16 | } 17 | 18 | defaultConfig { 19 | applicationId "me.ele.uetool.sample" 20 | minSdkVersion versions.minSdk 21 | targetSdkVersion versions.targetSdk 22 | versionCode 1 23 | versionName "1.0" 24 | } 25 | buildTypes { 26 | release { 27 | signingConfig signingConfigs.release 28 | minifyEnabled false 29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 30 | } 31 | } 32 | } 33 | 34 | dependencies { 35 | implementation "com.android.support:appcompat-v7:27.1.1" 36 | implementation "com.android.support:design:27.1.1" 37 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 38 | implementation "com.facebook.fresco:fresco:${versions.fresco}" 39 | implementation "com.facebook.fresco:animated-gif:${versions.fresco}" 40 | implementation 'com.android.support:appcompat-v7:28.0.0' 41 | implementation 'android.arch.lifecycle:extensions:1.1.1' 42 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 43 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4' 44 | releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4' 45 | 46 | debugImplementation project(':uetool') 47 | debugImplementation project(':uetool-fresco') 48 | debugImplementation project(':uetool-base') 49 | releaseImplementation project(':uetool-no-op') 50 | // debugImplementation "me.ele:uetool:${versions.release}" 51 | // debugImplementation "me.ele:uetool-fresco:${versions.release}" 52 | // releaseImplementation "me.ele:uetool-no-op:${versions.release}" 53 | 54 | compileOnly 'me.ele:lancet-base:1.0.6' 55 | 56 | configurations.all { 57 | resolutionStrategy.cacheChangingModulesFor 0, 'seconds' 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /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/debug/java/me/ele/uetool/sample/CustomAttribution.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import me.ele.uetool.base.Element; 7 | import me.ele.uetool.base.IAttrs; 8 | import me.ele.uetool.base.item.Item; 9 | import me.ele.uetool.base.item.TextItem; 10 | 11 | public class CustomAttribution implements IAttrs { 12 | 13 | @Override 14 | public List getAttrs(Element element) { 15 | List items = new ArrayList<>(); 16 | if (element.getView() instanceof CustomView) { 17 | CustomView view = (CustomView) element.getView(); 18 | items.add(new TextItem("More", view.getMoreAttribution())); 19 | } 20 | if (element.getView().getTag(R.id.uetool_xml) != null) { 21 | items.add(new TextItem("XML", element.getView().getTag(R.id.uetool_xml).toString())); 22 | } 23 | return items; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/debug/java/me/ele/uetool/sample/XmlLancet.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | 8 | import me.ele.lancet.base.Origin; 9 | import me.ele.lancet.base.annotations.Proxy; 10 | import me.ele.lancet.base.annotations.TargetClass; 11 | 12 | public class XmlLancet { 13 | 14 | @Proxy("inflate") 15 | @TargetClass(value = "android.view.LayoutInflater") 16 | public View inflate(int resourceId, ViewGroup root) { 17 | View view = (View) Origin.call(); 18 | traverse(view, getResourceName(view, resourceId)); 19 | return view; 20 | } 21 | 22 | @Proxy("inflate") 23 | @TargetClass(value = "android.view.LayoutInflater") 24 | public View inflate(int resourceId, ViewGroup root, boolean attachToRoot) { 25 | View view = (View) Origin.call(); 26 | traverse(view, getResourceName(view, resourceId)); 27 | return view; 28 | } 29 | 30 | @Proxy("inflate") 31 | @TargetClass(value = "android.view.View") 32 | public static View inflate(Context context, int resourceId, ViewGroup root) { 33 | View view = (View) Origin.call(); 34 | traverse(view, getResourceName(view, resourceId)); 35 | return view; 36 | } 37 | 38 | private static void traverse(View view, String name) { 39 | if (view.getTag(R.id.uetool_xml) == null) { 40 | view.setTag(R.id.uetool_xml, name); 41 | } 42 | if (view instanceof ViewGroup) { 43 | ViewGroup parent = (ViewGroup) view; 44 | for (int i = 0; i < parent.getChildCount(); i++) { 45 | traverse(parent.getChildAt(i), name); 46 | } 47 | } 48 | } 49 | 50 | private static String getResourceName(View view, int resourceId) { 51 | String resourceName = view.getResources().getResourceName(resourceId) + ".xml"; 52 | String[] splits = resourceName.split("/"); 53 | if (splits.length == 2) { 54 | return splits[1]; 55 | } 56 | return resourceName; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/debug/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/AppContext.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | 7 | import com.facebook.drawee.backends.pipeline.Fresco; 8 | import com.squareup.leakcanary.LeakCanary; 9 | 10 | import me.ele.uetool.UETool; 11 | 12 | public class AppContext extends Application { 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | LeakCanary.install(this); 18 | Fresco.initialize(this); 19 | 20 | UETool.putFilterClass(FilterOutView.class); 21 | UETool.putAttrsProviderClass(CustomAttribution.class); 22 | 23 | registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { 24 | 25 | private int visibleActivityCount; 26 | private int uetoolDismissY = -1; 27 | 28 | @Override 29 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 30 | 31 | } 32 | 33 | @Override 34 | public void onActivityStarted(Activity activity) { 35 | visibleActivityCount++; 36 | if (visibleActivityCount == 1 && uetoolDismissY >= 0) { 37 | UETool.showUETMenu(uetoolDismissY); 38 | } 39 | } 40 | 41 | @Override 42 | public void onActivityResumed(Activity activity) { 43 | 44 | } 45 | 46 | @Override 47 | public void onActivityPaused(Activity activity) { 48 | 49 | } 50 | 51 | @Override 52 | public void onActivityStopped(Activity activity) { 53 | visibleActivityCount--; 54 | if (visibleActivityCount == 0) { 55 | uetoolDismissY = UETool.dismissUETMenu(); 56 | } 57 | } 58 | 59 | @Override 60 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 61 | 62 | } 63 | 64 | @Override 65 | public void onActivityDestroyed(Activity activity) { 66 | 67 | } 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/CustomDialog.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.view.WindowManager; 8 | 9 | public class CustomDialog extends Dialog { 10 | 11 | public CustomDialog(@NonNull Context context) { 12 | super(context); 13 | } 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.dialog_layout); 19 | } 20 | 21 | @Override 22 | public void show() { 23 | super.show(); 24 | WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); 25 | layoutParams.setTitle("???"); 26 | layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; 27 | layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 28 | getWindow().setAttributes(layoutParams); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/CustomLayout.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.widget.FrameLayout; 9 | 10 | public class CustomLayout extends FrameLayout { 11 | public CustomLayout(@NonNull Context context) { 12 | this(context, null); 13 | } 14 | 15 | public CustomLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 16 | this(context, attrs, 0); 17 | } 18 | 19 | public CustomLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 20 | super(context, attrs, defStyleAttr); 21 | View.inflate(context, R.layout.custom_layout, this); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/CustomView.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.AppCompatTextView; 6 | import android.util.AttributeSet; 7 | 8 | public class CustomView extends AppCompatTextView { 9 | 10 | private String moreAttribution; 11 | 12 | public CustomView(Context context) { 13 | super(context); 14 | } 15 | 16 | public CustomView(Context context, @Nullable AttributeSet attrs) { 17 | super(context, attrs); 18 | } 19 | 20 | public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 21 | super(context, attrs, defStyleAttr); 22 | } 23 | 24 | public String getMoreAttribution() { 25 | return moreAttribution; 26 | } 27 | 28 | public void setMoreAttribution(String moreAttribution) { 29 | this.moreAttribution = moreAttribution; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/FilterOutView.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.AppCompatTextView; 6 | import android.util.AttributeSet; 7 | 8 | public class FilterOutView extends AppCompatTextView { 9 | public FilterOutView(Context context) { 10 | super(context); 11 | } 12 | 13 | public FilterOutView(Context context, @Nullable AttributeSet attrs) { 14 | super(context, attrs); 15 | } 16 | 17 | public FilterOutView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 18 | super(context, attrs, defStyleAttr); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/FragmentSampleActivity.kt: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | import me.ele.uetool.sample.ui.fragmentsample.FragmentSampleFragment 6 | 7 | class FragmentSampleActivity : AppCompatActivity() { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.fragment_sample_activity) 12 | if (savedInstanceState == null) { 13 | supportFragmentManager.beginTransaction() 14 | .replace(R.id.container, FragmentSampleFragment.newInstance()) 15 | .commitNow() 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Typeface; 5 | import android.graphics.drawable.Drawable; 6 | import android.os.Bundle; 7 | import android.support.v4.content.ContextCompat; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.SwitchCompat; 10 | import android.text.Spannable; 11 | import android.text.SpannableString; 12 | import android.view.View; 13 | import android.widget.CompoundButton; 14 | import android.widget.TextView; 15 | 16 | import com.facebook.drawee.backends.pipeline.Fresco; 17 | import com.facebook.drawee.interfaces.DraweeController; 18 | import com.facebook.drawee.view.SimpleDraweeView; 19 | 20 | import me.ele.uetool.UETool; 21 | import me.ele.uetool.sample.ui.recyclerviewsample.RecyclerViewActivity; 22 | 23 | public class MainActivity extends AppCompatActivity { 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | 30 | final SwitchCompat control = findViewById(R.id.control); 31 | control.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 32 | @Override 33 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 34 | if (isChecked) { 35 | if (!UETool.showUETMenu()) { 36 | control.setChecked(false); 37 | } 38 | } else { 39 | UETool.dismissUETMenu(); 40 | } 41 | } 42 | }); 43 | control.setChecked(true); 44 | 45 | updateDraweeView(); 46 | updateSpanTextView(); 47 | updateCustomView(); 48 | updateFontView(); 49 | } 50 | 51 | public void onClick(View view) { 52 | switch (view.getId()) { 53 | case R.id.btn1: 54 | startActivity(new Intent(this, SecondActivity.class)); 55 | break; 56 | case R.id.btn2: 57 | new CustomDialog(this).show(); 58 | break; 59 | case R.id.btn3: 60 | startActivity(new Intent(this, FragmentSampleActivity.class)); 61 | break; 62 | case R.id.btn4: 63 | startActivity(new Intent(this, RecyclerViewActivity.class)); 64 | } 65 | } 66 | 67 | private void updateDraweeView() { 68 | SimpleDraweeView draweeView = findViewById(R.id.drawee_view); 69 | DraweeController draweeController = Fresco.newDraweeControllerBuilder() 70 | .setUri("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561443230828&di=066c39a584cfe5cdcb244cc3af74afff&imgtype=0&src=http%3A%2F%2Fzkres1.myzaker.com%2F201905%2F5cda353b77ac6420a360a53f_320.jpg") 71 | .setAutoPlayAnimations(true) 72 | .build(); 73 | draweeView.setController(draweeController); 74 | } 75 | 76 | private void updateSpanTextView() { 77 | TextView spanTextView = findViewById(R.id.span); 78 | SpannableString spannableString = new SpannableString(" 海底捞火锅"); 79 | Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_food_new); 80 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 81 | VerticalImageSpan imageSpan = new VerticalImageSpan(drawable); 82 | spannableString.setSpan(imageSpan, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 83 | spanTextView.setText(spannableString); 84 | } 85 | 86 | private void updateCustomView() { 87 | final CustomView customView = findViewById(R.id.custom); 88 | customView.setMoreAttribution("more attribution"); 89 | Drawable drawable = ContextCompat.getDrawable(this, R.drawable.ic_up_vote); 90 | drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); 91 | customView.setCompoundDrawables(null, drawable, null, null); 92 | } 93 | 94 | private void updateFontView() { 95 | final TextView fontView = findViewById(R.id.font_test); 96 | fontView.setTypeface(Typeface.create("casual", Typeface.BOLD)); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | 9 | public class SecondActivity extends AppCompatActivity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_second); 15 | 16 | FloatingActionButton fab = findViewById(R.id.fab); 17 | fab.setOnClickListener(new View.OnClickListener() { 18 | @Override 19 | public void onClick(View view) { 20 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show(); 21 | } 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/VerticalImageSpan.java: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.Rect; 6 | import android.graphics.drawable.Drawable; 7 | import android.text.style.ImageSpan; 8 | 9 | public class VerticalImageSpan extends ImageSpan { 10 | 11 | public VerticalImageSpan(Drawable drawable) { 12 | super(drawable); 13 | } 14 | 15 | @Override 16 | public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fontMetricsInt) { 17 | Drawable drawable = getDrawable(); 18 | Rect rect = drawable.getBounds(); 19 | if (fontMetricsInt != null) { 20 | Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); 21 | int fontHeight = fmPaint.descent - fmPaint.ascent; 22 | int drHeight = rect.bottom - rect.top; 23 | int centerY = fmPaint.ascent + fontHeight / 2; 24 | 25 | fontMetricsInt.ascent = centerY - drHeight / 2; 26 | fontMetricsInt.top = fontMetricsInt.ascent; 27 | fontMetricsInt.bottom = centerY + drHeight / 2; 28 | fontMetricsInt.descent = fontMetricsInt.bottom; 29 | } 30 | return rect.right; 31 | } 32 | 33 | @Override 34 | public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { 35 | Drawable drawable = getDrawable(); 36 | canvas.save(); 37 | Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); 38 | int fontHeight = fmPaint.descent - fmPaint.ascent; 39 | int centerY = y + fmPaint.descent - fontHeight / 2; 40 | int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2; 41 | canvas.translate(x, transY); 42 | drawable.draw(canvas); 43 | canvas.restore(); 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/ui/fragmentsample/FragmentSampleFragment.kt: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample.ui.fragmentsample 2 | 3 | import android.arch.lifecycle.ViewModelProviders 4 | import android.os.Bundle 5 | import android.support.v4.app.Fragment 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import me.ele.uetool.sample.R 10 | 11 | class FragmentSampleFragment : Fragment() { 12 | 13 | companion object { 14 | fun newInstance() = FragmentSampleFragment() 15 | } 16 | 17 | private lateinit var viewModel: FragmentSampleViewModel 18 | 19 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 20 | savedInstanceState: Bundle?): View { 21 | return inflater.inflate(R.layout.fragment_sample_fragment, container, false) 22 | } 23 | 24 | override fun onActivityCreated(savedInstanceState: Bundle?) { 25 | super.onActivityCreated(savedInstanceState) 26 | viewModel = ViewModelProviders.of(this).get(FragmentSampleViewModel::class.java) 27 | // TODO: Use the ViewModel 28 | 29 | childFragmentManager.beginTransaction() 30 | .replace(R.id.container, FragmentSampleFragment2.newInstance()) 31 | .commitNow() 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/ui/fragmentsample/FragmentSampleFragment2.kt: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample.ui.fragmentsample 2 | 3 | import android.os.Bundle 4 | import android.support.v4.app.Fragment 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import me.ele.uetool.sample.R 9 | 10 | class FragmentSampleFragment2 : Fragment() { 11 | 12 | companion object { 13 | fun newInstance() = FragmentSampleFragment2() 14 | } 15 | 16 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 17 | savedInstanceState: Bundle?): View { 18 | return inflater.inflate(R.layout.fragment_sample_fragment, container, false) 19 | } 20 | 21 | override fun onActivityCreated(savedInstanceState: Bundle?) { 22 | super.onActivityCreated(savedInstanceState) 23 | 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/ui/fragmentsample/FragmentSampleViewModel.kt: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample.ui.fragmentsample 2 | 3 | import android.arch.lifecycle.ViewModel 4 | 5 | class FragmentSampleViewModel : ViewModel() { 6 | // TODO: Implement the ViewModel 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/me/ele/uetool/sample/ui/recyclerviewsample/RecyclerViewActivity.kt: -------------------------------------------------------------------------------- 1 | package me.ele.uetool.sample.ui.recyclerviewsample 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | import android.support.v7.widget.LinearLayoutManager 6 | import android.support.v7.widget.RecyclerView 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.widget.TextView 11 | import me.ele.uetool.sample.R 12 | 13 | class RecyclerViewActivity : AppCompatActivity() { 14 | var recyclerView: RecyclerView? = null 15 | 16 | override fun onCreate(savedInstanceState: Bundle?) { 17 | super.onCreate(savedInstanceState) 18 | setContentView(R.layout.activity_recycler_view) 19 | val list: ArrayList = ArrayList() 20 | for (i in 0..999) { 21 | val item = when (i % 3) { 22 | 0 -> Item1() 23 | 1 -> Item2() 24 | else -> Item3() 25 | } 26 | list.add(item) 27 | } 28 | recyclerView = findViewById(R.id.recycler) 29 | recyclerView?.layoutManager = LinearLayoutManager(this) 30 | recyclerView?.adapter = SimpleAdapter(list) 31 | } 32 | } 33 | 34 | 35 | class SimpleAdapter(private val items: List) : RecyclerView.Adapter() { 36 | companion object { 37 | const val TYPE1: Int = 1 38 | const val TYPE2: Int = 2 39 | const val TYPE3: Int = 3 40 | } 41 | 42 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { 43 | val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_simple_textview, parent, false) 44 | return when (viewType) { 45 | TYPE2 -> ViewHolder2(view) 46 | TYPE3 -> ViewHolder3(view) 47 | else -> ViewHolder1(view) 48 | } 49 | } 50 | 51 | override fun getItemCount(): Int { 52 | return items.size 53 | } 54 | 55 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { 56 | val view: TextView = holder.itemView as TextView 57 | view.text = position.toString() 58 | } 59 | 60 | override fun getItemViewType(position: Int): Int { 61 | return when (items[position]) { 62 | is Item1 -> TYPE1 63 | is Item2 -> TYPE2 64 | is Item3 -> TYPE3 65 | else -> 0 66 | } 67 | } 68 | } 69 | 70 | interface Item 71 | 72 | class Item1 : Item 73 | class Item2 : Item 74 | class Item3 : Item 75 | 76 | class ViewHolder1(itemView: View) : RecyclerView.ViewHolder(itemView) 77 | class ViewHolder2(itemView: View) : RecyclerView.ViewHolder(itemView) 78 | class ViewHolder3(itemView: View) : RecyclerView.ViewHolder(itemView) -------------------------------------------------------------------------------- /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-xxhdpi/ic_down_vote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/app/src/main/res/drawable-xxhdpi/ic_down_vote.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_food_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/app/src/main/res/drawable-xxhdpi/ic_food_new.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/app/src/main/res/drawable-xxhdpi/ic_placeholder.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_tip.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/app/src/main/res/drawable-xxhdpi/ic_tip.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_up_vote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eleme/UETool/e4967a5fae89f94561917ab95ca40c6e414a25ec/app/src/main/res/drawable-xxhdpi/ic_up_vote.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 172 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 19 | 20 | 23 | 24 | 30 | 31 | 41 | 42 | 43 | 44 | 48 | 49 | 59 | 60 | 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | 77 | 78 |