├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── findbugs-idea.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── build.gradle └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── blog │ │ └── www │ │ └── swipebackactivity │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── file │ └── review.gif │ ├── java │ └── com │ │ └── binioter │ │ ├── app │ │ └── AppManager.java │ │ ├── base │ │ └── BaseActivity.java │ │ ├── ui │ │ ├── CommonDialogActivity.java │ │ ├── FlowLayoutActivity.java │ │ ├── MainActivity.java │ │ └── TipTextViewActivity.java │ │ ├── utils │ │ ├── SystemBarTintManager.java │ │ └── TitleBarHelper.java │ │ └── widget │ │ ├── SwipeBackLayout.java │ │ └── TopTitleBar.java │ └── res │ ├── layout │ ├── activity_common_dialog_layout.xml │ ├── activity_flowtag_layout.xml │ ├── activity_main.xml │ └── tip_textview_activity_layout.xml │ ├── menu │ ├── menu_base.xml │ ├── menu_main.xml │ └── menu_second.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ ├── btn_back_normal.png │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── commonutil ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── binioter │ │ └── util │ │ ├── DensityUtil.java │ │ └── UIUtils.java │ └── res │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── dialog ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── binioter │ │ └── dialog │ │ ├── CustomDialog.java │ │ └── DialogUtil.java │ └── res │ ├── layout │ └── custom_dialog_layout.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-v5 │ └── styles.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── flowtag ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── binioter │ │ └── flowtag │ │ ├── ColorTag.java │ │ ├── ColorTagView.java │ │ ├── FlowLayout.java │ │ └── TagUtil.java │ └── res │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── settings.gradle └── tiptextview └── src └── main └── java └── com └── binioter └── tiptextview └── TipTextView.java /.gitignore: -------------------------------------------------------------------------------- 1 | #Android generated 2 | bin 3 | gen 4 | lint.xml 5 | proguard 6 | 7 | #Eclipse 8 | .project 9 | .classpath 10 | .settings 11 | .checkstyle 12 | 13 | #IntelliJ IDEA 14 | .idea 15 | *.iml 16 | *.ipr 17 | *.iws 18 | captures 19 | gen-external-apklibs 20 | 21 | #gradle 22 | .gradle 23 | local.properties 24 | gradle.properties 25 | gradlew 26 | gradlew.bat 27 | gradle/ 28 | build 29 | 30 | 31 | #vi 32 | *.swp 33 | 34 | #other editors 35 | *.bak 36 | 37 | #Maven 38 | target 39 | release.properties 40 | pom.xml.* 41 | 42 | #Ant 43 | build.xml 44 | ant.properties 45 | proguard.cfg 46 | proguard-project.txt 47 | 48 | #Other 49 | .DS_Store 50 | Thumbs.db 51 | *.tgz 52 | *.lck 53 | com_crashlytics_export_strings.xml 54 | 55 | #review 56 | reviewers.txt 57 | 58 | nuwapatch/ 59 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | SwipeBackActivity -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/findbugs-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 32 | 203 | 216 | 225 | 226 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | Android API 19 Platform 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 简介
2 | CommonApp,旨在帮助开发者进行组件化开发,包含了App通用的模块,各个模块采用单独module进行维护,目前包含以下模块:
3 | * 沉浸式状态栏模块 4 | * 通用的titlebar模块 5 | * Activity堆栈管理器模块 6 | * 全局右滑关闭页面模块 7 | * 通用dialog,流式标签模块 8 | * 带动画的提示TextView 9 | * 持续更新中...
10 | ![image](https://github.com/binIoter/CommonApp/blob/master/app/src/main/file/review.gif ) 11 | 12 | 13 | ## usage
14 | 在BaseActivity中进行初始化,并且通过调用setSwipeBackEnabled()方法控制当前Activity是否可以右滑关闭
15 | 16 | public class BaseActivity extends Activity { 17 | protected SwipeBackLayout mSwipeBackLayout; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_base); 23 | mSwipeBackLayout = new SwipeBackLayout(this); 24 | mSwipeBackLayout.attachToActivity(this); 25 | mSwipeBackLayout.setBgTransparent(); 26 | SystemBarTintManager tintManager = new SystemBarTintManager(this); 27 | // enable status bar tint 28 | tintManager.setStatusBarTintEnabled(true); 29 | // enable navigation bar tint 30 | tintManager.setNavigationBarTintEnabled(true); 31 | tintManager.setStatusBarTintResource(getResources().getColor(R.color.title_bar_color)); 32 | if (hasKitKat() && !hasLollipop()) { 33 | // 透明状态栏 34 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 35 | // 透明导航栏 36 | // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 37 | } else if (hasLollipop()) { 38 | Window window = getWindow(); 39 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | 40 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 41 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 42 | // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 43 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 44 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 45 | window.setStatusBarColor(getColor(R.color.title_bar_color)); 46 | } 47 | } 48 | /** 49 | * 是否禁用滑动返回 50 | */ 51 | public void setSwipeBackEnabled(boolean isSwipeBackEnabled) { 52 | mSwipeBackLayout.setSwipeBackEnabled(isSwipeBackEnabled); 53 | } 54 | } 55 |
styles文件设置
56 | 57 | 62 | 63 | 64 | 65 |
AndroidManifest.xml文件添加主题
66 | android:theme="@style/swipeback_activity_style" 67 | License 68 | ------- 69 | 70 | Copyright 2016 binIoter 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 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.blog.www.swipebackactivity" 9 | minSdkVersion 11 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | compile 'com.android.support:appcompat-v7:25.0.0' 25 | compile 'com.android.support:support-annotations' 26 | compile 'com.jakewharton:butterknife:7.0.1' 27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 28 | exclude group: 'com.android.support', module: 'support-annotations' 29 | }) 30 | testCompile 'junit:junit:4.12' 31 | compile project(':flowtag') 32 | compile project(':dialog') 33 | compile project(':tiptextview') 34 | } 35 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/blog/www/swipebackactivity/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.blog.www.swipebackactivity; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 25 | 28 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/file/review.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binIoter/CommonApp/b4e150994e294bad985d2f5a8ec3521fd75a72d1/app/src/main/file/review.gif -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/app/AppManager.java: -------------------------------------------------------------------------------- 1 | package com.binioter.app; 2 | 3 | import android.text.TextUtils; 4 | import java.lang.ref.SoftReference; 5 | import java.util.ArrayList; 6 | 7 | import android.app.Activity; 8 | 9 | /** 10 | * 维护应用Activity栈,用来控制栈的大小,超出则finish首页之后的若干个页面,至小于限制为止 上限值通过setActivityStackMaxSize设置,为0则不限制 11 | * 注意,这个行为在SDK中应该有所不同。 12 | */ 13 | final public class AppManager { 14 | private static ArrayList> sActivityStack; 15 | private static AppManager sInstance; 16 | 17 | private OnAllActivityClosed mActivityClosed; 18 | 19 | // Activity栈的MaxSize,为0表示不限制 20 | private int mActivityStackMaxSize = 0; 21 | 22 | /** 23 | * 设置所有的Activity都关闭了的监听回调 24 | * 25 | * @param activityClosed 26 | * 回调 27 | */ 28 | public void setOnActivityAllClosed(OnAllActivityClosed activityClosed) { 29 | mActivityClosed = activityClosed; 30 | } 31 | 32 | private AppManager() { 33 | if (sActivityStack == null) { 34 | sActivityStack = new ArrayList>(20); 35 | } 36 | // BdLog.addLogPackage("com.baidu.adp.base.BdActivityStack"); 37 | } 38 | 39 | /** 40 | * 得到单例 41 | * 42 | * @return 43 | */ 44 | public static AppManager getInst() { 45 | if (sInstance == null) { 46 | sInstance = new AppManager(); 47 | } 48 | return sInstance; 49 | } 50 | 51 | /** 52 | * 得到当前Activity栈里面的管理的Activity的数量 53 | * 54 | * @return 55 | */ 56 | public int getSize() { 57 | return sActivityStack.size(); 58 | } 59 | 60 | /** 61 | * 向Activity栈中压入一个Activity 62 | * 63 | * @param activity 64 | */ 65 | public void pushActivity(Activity activity) { 66 | // BdLog.d("Activity pushed: " + activity); 67 | if (activity != null) { 68 | sActivityStack.add(new SoftReference(activity)); 69 | checkAndMaintainActivityStack(mActivityStackMaxSize); 70 | } 71 | } 72 | 73 | /** 74 | * 从Activity栈中移除最上面的Activity 75 | * 76 | * @return 返回移除的Activity 77 | */ 78 | public Activity popActivity() { 79 | int size = sActivityStack.size(); 80 | if (size == 0) { 81 | return null; 82 | } 83 | SoftReference sr = sActivityStack.remove(size - 1); 84 | if (sr == null) { 85 | return null; 86 | } 87 | Activity activity = sr.get(); 88 | // BdLog.d("Activity popped: " + activity); 89 | return activity; 90 | } 91 | 92 | /** 93 | * 从Activity栈中移除某个index对应的Activity 94 | * 95 | * @param index 96 | * 索引 97 | * @return 返回移除的Activity 98 | */ 99 | public Activity popActivity(int index) { 100 | int size = sActivityStack.size(); 101 | if (size == 0) { 102 | return null; 103 | } 104 | if (index < 0 || index >= size) { 105 | return null; 106 | } 107 | SoftReference sr = sActivityStack.remove(index); 108 | if (sr == null) { 109 | return null; 110 | } 111 | Activity activity = sr.get(); 112 | return activity; 113 | } 114 | 115 | /** 116 | * 从Activity栈中移除某个指定的Activity 117 | * 118 | * @param activity 119 | * 要移除的Activity 120 | */ 121 | public void popActivity(Activity activity) { 122 | if (activity != null) { 123 | int size = sActivityStack.size(); 124 | if (size == 0) { 125 | if (mActivityClosed != null) { 126 | mActivityClosed.onActivityClosed(); 127 | } 128 | return; 129 | } 130 | 131 | for (int i = size - 1; i >= 0; i--) { 132 | SoftReference sr = sActivityStack.get(i); 133 | if (sr == null) { 134 | sActivityStack.remove(i); 135 | continue; 136 | } 137 | 138 | Activity item = sr.get(); 139 | if (activity.equals(item)) { 140 | sActivityStack.remove(i); 141 | if (sActivityStack.size() == 0) { 142 | if (mActivityClosed != null) { 143 | mActivityClosed.onActivityClosed(); 144 | } 145 | } 146 | return; 147 | } 148 | 149 | if (sActivityStack.size() == 0) { 150 | if (mActivityClosed != null) { 151 | mActivityClosed.onActivityClosed(); 152 | } 153 | } 154 | } 155 | } 156 | } 157 | 158 | /** 159 | * 得到当前处于栈顶的Activity 160 | * 161 | * @return 162 | */ 163 | public Activity currentActivity() { 164 | int size = sActivityStack.size(); 165 | if (size == 0) { 166 | return null; 167 | } 168 | SoftReference sr = sActivityStack.get(size - 1); 169 | if (sr == null) { 170 | return null; 171 | } 172 | Activity activity = sr.get(); 173 | return activity; 174 | } 175 | 176 | /** 177 | * 设置Activity栈的最大数量 178 | * 179 | * @param size 180 | */ 181 | public void setActivityStackMaxSize(int size) { 182 | // 不允许小于10 183 | if (size < 10 && size != 0) { 184 | return; 185 | } 186 | mActivityStackMaxSize = size; 187 | } 188 | 189 | /** 190 | * 保留3个Activity,其他的Activity都释放移除并且finish 191 | */ 192 | public void releaseAllPossibleAcitivities() { 193 | this.checkAndMaintainActivityStack(3); 194 | } 195 | 196 | /** 197 | * 清空Activity栈,所有的Activity都释放移除并且finish 198 | */ 199 | public void releaseAllAcitivities() { 200 | if (sActivityStack != null) { 201 | while (!sActivityStack.isEmpty()) { 202 | SoftReference act = sActivityStack.remove(0); 203 | 204 | if (act != null && act.get() != null) { 205 | Activity activity = act.get(); 206 | if (activity != null) { 207 | activity.finish(); 208 | } 209 | } 210 | } 211 | } 212 | 213 | if (mActivityClosed != null) { 214 | mActivityClosed.onActivityClosed(); 215 | } 216 | } 217 | 218 | /** 219 | * 获得Activity栈的最大数量 220 | * 221 | * @see AppManager 222 | * @return 223 | */ 224 | public int getActivityStackMaxSize() { 225 | return mActivityStackMaxSize; 226 | } 227 | 228 | private void checkAndMaintainActivityStack(int activityStackMaxSize) { 229 | if (activityStackMaxSize == 0) { 230 | return; 231 | } 232 | 233 | int currentSize = AppManager.getInst().getSize(); 234 | while (currentSize > activityStackMaxSize) { 235 | currentSize--; 236 | // remove the second bottom. 237 | Activity act = AppManager.getInst().popActivity(1); 238 | if (act != null) { 239 | act.finish(); 240 | } 241 | } 242 | } 243 | 244 | /** 245 | * Activity全部关闭时调用的接口 246 | * 247 | * @author libin18 248 | * 249 | */ 250 | public interface OnAllActivityClosed { 251 | public void onActivityClosed(); 252 | } 253 | 254 | /** 255 | * 获取当前栈中的所有Activity名称 256 | */ 257 | public String getActivityStack() { 258 | if (sActivityStack == null || sActivityStack.size() == 0) { 259 | return ""; 260 | } 261 | 262 | StringBuilder builder = new StringBuilder(); 263 | 264 | for (SoftReference softActivity : sActivityStack) { 265 | if (softActivity == null) { 266 | continue; 267 | } 268 | 269 | Activity activity = softActivity.get(); 270 | if (activity == null) { 271 | continue; 272 | } 273 | String className = ""; 274 | if ((activity != null) && (activity.getClass() != null)) { 275 | className = activity.getClass().getSimpleName(); 276 | } 277 | // } 278 | 279 | if (TextUtils.isEmpty(className)) { 280 | continue; 281 | } 282 | 283 | builder.append(className + ";"); 284 | } 285 | return builder.toString(); 286 | } 287 | 288 | } 289 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.binioter.base; 2 | 3 | import android.app.Activity; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | import com.binioter.R; 10 | import com.binioter.app.AppManager; 11 | import com.binioter.util.DensityUtil; 12 | import com.binioter.util.UIUtils; 13 | import com.binioter.utils.SystemBarTintManager; 14 | import com.binioter.utils.TitleBarHelper; 15 | import com.binioter.widget.SwipeBackLayout; 16 | import com.binioter.widget.TopTitleBar; 17 | 18 | public class BaseActivity extends Activity { 19 | 20 | protected SwipeBackLayout mSwipeBackLayout; 21 | protected TopTitleBar topTitleBar; 22 | protected int mTitleBarHeight = 47; 23 | 24 | @Override protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | mTitleBarHeight = DensityUtil.px2dip(this, getResources().getDimension(R.dimen.title_height)); 27 | AppManager.getInst().pushActivity(this); 28 | mSwipeBackLayout = new SwipeBackLayout(this); 29 | mSwipeBackLayout.attachToActivity(this); 30 | mSwipeBackLayout.setBgTransparent(); 31 | SystemBarTintManager tintManager = new SystemBarTintManager(this); 32 | // enable status bar tint 33 | tintManager.setStatusBarTintEnabled(true); 34 | // enable navigation bar tint 35 | tintManager.setNavigationBarTintEnabled(true); 36 | tintManager.setStatusBarTintResource(getResources().getColor(R.color.title_bar_color)); 37 | if (hasKitKat() && !hasLollipop()) { 38 | // 透明状态栏 39 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 40 | // 透明导航栏 41 | // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 42 | } else if (hasLollipop()) { 43 | Window window = getWindow(); 44 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 45 | | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 46 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 47 | // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 48 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 49 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 50 | window.setStatusBarColor(UIUtils.getColor(this, R.color.title_bar_color)); 51 | } 52 | } 53 | 54 | protected void initBar(TopTitleBar mTitlebar) { 55 | new TitleBarHelper(this, mTitlebar).init(); 56 | } 57 | 58 | /** 59 | * 是否禁用滑动返回 60 | */ 61 | public void setSwipeBackEnabled(boolean isSwipeBackEnabled) { 62 | mSwipeBackLayout.setSwipeBackEnabled(isSwipeBackEnabled); 63 | } 64 | 65 | public static boolean hasKitKat() { 66 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 67 | } 68 | 69 | public static boolean hasLollipop() { 70 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; 71 | } 72 | 73 | @Override protected void onDestroy() { 74 | super.onDestroy(); 75 | AppManager.getInst().popActivity(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/ui/CommonDialogActivity.java: -------------------------------------------------------------------------------- 1 | package com.binioter.ui; 2 | 3 | import android.content.DialogInterface; 4 | import android.os.Bundle; 5 | import butterknife.Bind; 6 | import butterknife.ButterKnife; 7 | import butterknife.OnClick; 8 | import com.binioter.R; 9 | import com.binioter.base.BaseActivity; 10 | import com.binioter.dialog.DialogUtil; 11 | import com.binioter.widget.TopTitleBar; 12 | 13 | /** 14 | * 创建时间: 2016/11/24 16:56
15 | * 作者: zhangbin
16 | * 描述: 通用dialog activity 17 | */ 18 | 19 | public class CommonDialogActivity extends BaseActivity { 20 | 21 | @Bind(R.id.title_bar) TopTitleBar mTitleBar; 22 | 23 | @Override protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_common_dialog_layout); 26 | ButterKnife.bind(this); 27 | initBar(mTitleBar); 28 | //低级api 29 | //new CustomDialog.Builder(this).create().show(); 30 | } 31 | 32 | @OnClick(R.id.btn_no_title_one_btn) void onBtnNoTitleOneBtn() { 33 | DialogUtil.createDialogButton(this, "我是没有标题有一个按钮的弹窗", "我知道了", 34 | new DialogInterface.OnClickListener() { 35 | @Override public void onClick(DialogInterface dialogInterface, int i) { 36 | dialogInterface.dismiss(); 37 | } 38 | }).show(); 39 | } 40 | 41 | @OnClick(R.id.btn_no_title_two_btn) void onBtnNoTitleTwoBtn() { 42 | DialogUtil.createDialog2Button(this, "我是没有标题和两个按钮的弹窗", "取消", 43 | new DialogInterface.OnClickListener() { 44 | @Override public void onClick(DialogInterface dialogInterface, int i) { 45 | dialogInterface.dismiss(); 46 | } 47 | }, "确定", new DialogInterface.OnClickListener() { 48 | @Override public void onClick(DialogInterface dialogInterface, int i) { 49 | dialogInterface.dismiss(); 50 | } 51 | }).show(); 52 | } 53 | 54 | @OnClick(R.id.btn_with_title_one_btn) void onBtnWithTitleOneBtn() { 55 | DialogUtil.createDialogMsg(this, "弹窗标题", "我是有标题有一个按钮的弹窗", "我知道了", 56 | new DialogInterface.OnClickListener() { 57 | @Override public void onClick(DialogInterface dialogInterface, int i) { 58 | dialogInterface.dismiss(); 59 | } 60 | }).show(); 61 | } 62 | 63 | @OnClick(R.id.btn_with_title_two_btn) void onBtnWithTitleTwoBtn() { 64 | DialogUtil.createDialog2ButtonMsg(this, "弹窗标题", "我是有标题和两个按钮的弹窗", "取消", 65 | new DialogInterface.OnClickListener() { 66 | @Override public void onClick(DialogInterface dialogInterface, int i) { 67 | dialogInterface.dismiss(); 68 | } 69 | }, "确定", new DialogInterface.OnClickListener() { 70 | @Override public void onClick(DialogInterface dialogInterface, int i) { 71 | dialogInterface.dismiss(); 72 | } 73 | }).show(); 74 | } 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/ui/FlowLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.binioter.ui; 2 | 3 | import android.os.Bundle; 4 | import butterknife.Bind; 5 | import butterknife.ButterKnife; 6 | import com.binioter.R; 7 | import com.binioter.base.BaseActivity; 8 | import com.binioter.flowtag.ColorTag; 9 | import com.binioter.flowtag.ColorTagView; 10 | import com.binioter.flowtag.FlowLayout; 11 | import com.binioter.widget.TopTitleBar; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Random; 15 | 16 | /** 17 | * 创建时间: 2016/11/25 10:44
18 | * 作者: zhangbin
19 | * 描述: 流式标签activity 20 | */ 21 | 22 | public class FlowLayoutActivity extends BaseActivity { 23 | @Bind(R.id.flow_layout) FlowLayout mFlowLayout; 24 | @Bind(R.id.title_bar) TopTitleBar mTitleBar; 25 | private List mTagData = new ArrayList<>(); 26 | private static String mTagType[] = { "有电梯", "绿化率高", "小区环境好", "安静", "南北通透税费低" }; 27 | private static String mTagColor[] = { "394043", "be5453", "00ae66", "b27f39", "ae005d" }; 28 | 29 | @Override protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_flowtag_layout); 32 | ButterKnife.bind(this); 33 | initBar(mTitleBar); 34 | initData(); 35 | initView(); 36 | } 37 | 38 | private void initView() { 39 | mFlowLayout.removeAllViews(); 40 | for (int i = 0; i < mTagData.size(); i++) { 41 | mFlowLayout.addView(new ColorTagView(this, mTagData.get(i))); 42 | } 43 | } 44 | 45 | private void initData() { 46 | Random random = new Random(); 47 | for (int i = 0; i < 30; i++) { 48 | ColorTag colorTag = new ColorTag(); 49 | colorTag.text = mTagType[random.nextInt(5)]; 50 | colorTag.color = mTagColor[random.nextInt(5)]; 51 | mTagData.add(colorTag); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.binioter.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import butterknife.ButterKnife; 6 | import butterknife.OnClick; 7 | import com.binioter.R; 8 | import com.binioter.base.BaseActivity; 9 | import com.binioter.widget.TopTitleBar; 10 | 11 | public class MainActivity extends BaseActivity { 12 | 13 | @Override protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_main); 16 | ButterKnife.bind(this); 17 | setSwipeBackEnabled(false); 18 | initTitleBar(); 19 | } 20 | 21 | private void initTitleBar() { 22 | TopTitleBar topTitleBar = (TopTitleBar) findViewById(R.id.title_bar); 23 | topTitleBar.setTitle("首页"); 24 | topTitleBar.setLeftVisible(false); 25 | initBar(topTitleBar); 26 | } 27 | 28 | @OnClick(R.id.btn_jump_dialog_aty) void onBtnJumpDialogAty() { 29 | startActivity(new Intent(MainActivity.this, CommonDialogActivity.class)); 30 | } 31 | 32 | @OnClick(R.id.btn_jump_flow_aty) void onBtnJumpFlowAty() { 33 | startActivity(new Intent(MainActivity.this, FlowLayoutActivity.class)); 34 | } 35 | 36 | @OnClick(R.id.btn_jump_tips_aty) void onBtnJumpTIpsAty() { 37 | startActivity(new Intent(MainActivity.this, TipTextViewActivity.class)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/ui/TipTextViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.binioter.ui; 2 | 3 | import android.os.Bundle; 4 | import android.widget.Button; 5 | import butterknife.Bind; 6 | import butterknife.ButterKnife; 7 | import butterknife.OnClick; 8 | import com.binioter.R; 9 | import com.binioter.base.BaseActivity; 10 | import com.binioter.tiptextview.TipTextView; 11 | import com.binioter.util.DensityUtil; 12 | import com.binioter.widget.TopTitleBar; 13 | 14 | /** 15 | * 创建时间: 2016/11/29 11:36
16 | * 作者: zhangbin
17 | * 描述: 弹出tips的Activity 18 | */ 19 | 20 | public class TipTextViewActivity extends BaseActivity { 21 | @Bind(R.id.btn_show) Button mBtnShow; 22 | @Bind(R.id.btn_hide) Button mBtnHide; 23 | @Bind(R.id.tip_tv) TipTextView mTipTv; 24 | @Bind(R.id.title_bar) TopTitleBar mTitleBar; 25 | 26 | @Override protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.tip_textview_activity_layout); 29 | ButterKnife.bind(this); 30 | initBar(mTitleBar); 31 | //因为是带有沉浸式状态栏所以要加上状态栏的高度,没有沉浸式状态栏,这行代码可以去掉,默认为titlebar的高度 32 | mTipTv.setHeight( 33 | DensityUtil.px2dip(this, DensityUtil.getStatusBarHeight(this)) + mTitleBarHeight); 34 | } 35 | 36 | @OnClick(R.id.btn_show) void showTips() { 37 | mTipTv.showTips(getResources().getString(R.string.txt_tips)); 38 | } 39 | 40 | @OnClick(R.id.btn_hide) void hideTips() { 41 | mTipTv.hideTips(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/utils/SystemBarTintManager.java: -------------------------------------------------------------------------------- 1 | package com.binioter.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.Context; 7 | import android.content.res.Configuration; 8 | import android.content.res.Resources; 9 | import android.content.res.TypedArray; 10 | import android.graphics.drawable.Drawable; 11 | import android.os.Build; 12 | import android.util.DisplayMetrics; 13 | import android.util.TypedValue; 14 | import android.view.Gravity; 15 | import android.view.View; 16 | import android.view.ViewConfiguration; 17 | import android.view.ViewGroup; 18 | import android.view.Window; 19 | import android.view.WindowManager; 20 | import android.widget.FrameLayout.LayoutParams; 21 | 22 | import java.lang.reflect.Method; 23 | 24 | /** 25 | * Class to manage status and navigation bar tint effects when using KitKat 26 | * translucent system UI modes. 27 | */ 28 | public class SystemBarTintManager { 29 | 30 | static { 31 | // Android allows a system property to override the presence of the navigation bar. 32 | // Used by the emulator. 33 | // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076 34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 35 | try { 36 | Class c = Class.forName("android.os.SystemProperties"); 37 | Method m = c.getDeclaredMethod("get", String.class); 38 | m.setAccessible(true); 39 | sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); 40 | } catch (Throwable e) { 41 | sNavBarOverride = null; 42 | } 43 | } 44 | } 45 | 46 | 47 | /** 48 | * The default system bar tint color value. 49 | */ 50 | public static final int DEFAULT_TINT_COLOR = 0x99000000; 51 | 52 | private static String sNavBarOverride; 53 | 54 | private final SystemBarConfig mConfig; 55 | private boolean mStatusBarAvailable; 56 | private boolean mNavBarAvailable; 57 | private boolean mStatusBarTintEnabled; 58 | private boolean mNavBarTintEnabled; 59 | private View mStatusBarTintView; 60 | private View mNavBarTintView; 61 | 62 | /** 63 | * Constructor. Call this in the host activity onCreate method after its 64 | * content view has been set. You should always create new instances when 65 | * the host activity is recreated. 66 | * 67 | * @param activity The host activity. 68 | */ 69 | @TargetApi(19) 70 | public SystemBarTintManager(Activity activity) { 71 | 72 | Window win = activity.getWindow(); 73 | ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); 74 | 75 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 76 | // check theme attrs 77 | int[] attrs = {android.R.attr.windowTranslucentStatus, 78 | android.R.attr.windowTranslucentNavigation}; 79 | TypedArray a = activity.obtainStyledAttributes(attrs); 80 | try { 81 | mStatusBarAvailable = a.getBoolean(0, false); 82 | mNavBarAvailable = a.getBoolean(1, false); 83 | } finally { 84 | a.recycle(); 85 | } 86 | 87 | // check window flags 88 | WindowManager.LayoutParams winParams = win.getAttributes(); 89 | int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 90 | if ((winParams.flags & bits) != 0) { 91 | mStatusBarAvailable = true; 92 | } 93 | bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 94 | if ((winParams.flags & bits) != 0) { 95 | mNavBarAvailable = true; 96 | } 97 | } 98 | 99 | mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable); 100 | // device might not have virtual navigation keys 101 | if (!mConfig.hasNavigtionBar()) { 102 | mNavBarAvailable = false; 103 | } 104 | 105 | if (mStatusBarAvailable) { 106 | setupStatusBarView(activity, decorViewGroup); 107 | } 108 | if (mNavBarAvailable) { 109 | setupNavBarView(activity, decorViewGroup); 110 | } 111 | 112 | } 113 | 114 | /** 115 | * Enable tinting of the system status bar. 116 | *

117 | * If the platform is running Jelly Bean or earlier, or translucent system 118 | * UI modes have not been enabled in either the theme or via window flags, 119 | * then this method does nothing. 120 | * 121 | * @param enabled True to enable tinting, false to disable it (default). 122 | */ 123 | public void setStatusBarTintEnabled(boolean enabled) { 124 | mStatusBarTintEnabled = enabled; 125 | if (mStatusBarAvailable) { 126 | mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 127 | } 128 | } 129 | 130 | /** 131 | * Enable tinting of the system navigation bar. 132 | *

133 | * If the platform does not have soft navigation keys, is running Jelly Bean 134 | * or earlier, or translucent system UI modes have not been enabled in either 135 | * the theme or via window flags, then this method does nothing. 136 | * 137 | * @param enabled True to enable tinting, false to disable it (default). 138 | */ 139 | public void setNavigationBarTintEnabled(boolean enabled) { 140 | mNavBarTintEnabled = enabled; 141 | if (mNavBarAvailable) { 142 | mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); 143 | } 144 | } 145 | 146 | /** 147 | * Apply the specified color tint to all system UI bars. 148 | * 149 | * @param color The color of the background tint. 150 | */ 151 | public void setTintColor(int color) { 152 | setStatusBarTintColor(color); 153 | setNavigationBarTintColor(color); 154 | } 155 | 156 | /** 157 | * Apply the specified drawable or color resource to all system UI bars. 158 | * 159 | * @param res The identifier of the resource. 160 | */ 161 | public void setTintResource(int res) { 162 | setStatusBarTintResource(res); 163 | setNavigationBarTintResource(res); 164 | } 165 | 166 | /** 167 | * Apply the specified drawable to all system UI bars. 168 | * 169 | * @param drawable The drawable to use as the background, or null to remove it. 170 | */ 171 | public void setTintDrawable(Drawable drawable) { 172 | setStatusBarTintDrawable(drawable); 173 | setNavigationBarTintDrawable(drawable); 174 | } 175 | 176 | /** 177 | * Apply the specified alpha to all system UI bars. 178 | * 179 | * @param alpha The alpha to use 180 | */ 181 | public void setTintAlpha(float alpha) { 182 | setStatusBarAlpha(alpha); 183 | setNavigationBarAlpha(alpha); 184 | } 185 | 186 | /** 187 | * Apply the specified color tint to the system status bar. 188 | * 189 | * @param color The color of the background tint. 190 | */ 191 | public void setStatusBarTintColor(int color) { 192 | if (mStatusBarAvailable) { 193 | mStatusBarTintView.setBackgroundColor(color); 194 | } 195 | } 196 | 197 | /** 198 | * Apply the specified drawable or color resource to the system status bar. 199 | * 200 | * @param res The identifier of the resource. 201 | */ 202 | public void setStatusBarTintResource(int res) { 203 | if (mStatusBarAvailable) { 204 | mStatusBarTintView.setBackgroundResource(res); 205 | } 206 | } 207 | 208 | /** 209 | * Apply the specified drawable to the system status bar. 210 | * 211 | * @param drawable The drawable to use as the background, or null to remove it. 212 | */ 213 | @SuppressWarnings("deprecation") 214 | public void setStatusBarTintDrawable(Drawable drawable) { 215 | if (mStatusBarAvailable) { 216 | mStatusBarTintView.setBackgroundDrawable(drawable); 217 | } 218 | } 219 | 220 | /** 221 | * Apply the specified alpha to the system status bar. 222 | * 223 | * @param alpha The alpha to use 224 | */ 225 | @TargetApi(11) 226 | public void setStatusBarAlpha(float alpha) { 227 | if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 228 | mStatusBarTintView.setAlpha(alpha); 229 | } 230 | } 231 | 232 | /** 233 | * Apply the specified color tint to the system navigation bar. 234 | * 235 | * @param color The color of the background tint. 236 | */ 237 | public void setNavigationBarTintColor(int color) { 238 | if (mNavBarAvailable) { 239 | mNavBarTintView.setBackgroundColor(color); 240 | } 241 | } 242 | 243 | /** 244 | * Apply the specified drawable or color resource to the system navigation bar. 245 | * 246 | * @param res The identifier of the resource. 247 | */ 248 | public void setNavigationBarTintResource(int res) { 249 | if (mNavBarAvailable) { 250 | mNavBarTintView.setBackgroundResource(res); 251 | } 252 | } 253 | 254 | /** 255 | * Apply the specified drawable to the system navigation bar. 256 | * 257 | * @param drawable The drawable to use as the background, or null to remove it. 258 | */ 259 | @SuppressWarnings("deprecation") 260 | public void setNavigationBarTintDrawable(Drawable drawable) { 261 | if (mNavBarAvailable) { 262 | mNavBarTintView.setBackgroundDrawable(drawable); 263 | } 264 | } 265 | 266 | /** 267 | * Apply the specified alpha to the system navigation bar. 268 | * 269 | * @param alpha The alpha to use 270 | */ 271 | @TargetApi(11) 272 | public void setNavigationBarAlpha(float alpha) { 273 | if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 274 | mNavBarTintView.setAlpha(alpha); 275 | } 276 | } 277 | 278 | /** 279 | * Get the system bar configuration. 280 | * 281 | * @return The system bar configuration for the current device configuration. 282 | */ 283 | public SystemBarConfig getConfig() { 284 | return mConfig; 285 | } 286 | 287 | /** 288 | * Is tinting enabled for the system status bar? 289 | * 290 | * @return True if enabled, False otherwise. 291 | */ 292 | public boolean isStatusBarTintEnabled() { 293 | return mStatusBarTintEnabled; 294 | } 295 | 296 | /** 297 | * Is tinting enabled for the system navigation bar? 298 | * 299 | * @return True if enabled, False otherwise. 300 | */ 301 | public boolean isNavBarTintEnabled() { 302 | return mNavBarTintEnabled; 303 | } 304 | 305 | private void setupStatusBarView(Context context, ViewGroup decorViewGroup) { 306 | mStatusBarTintView = new View(context); 307 | LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight()); 308 | params.gravity = Gravity.TOP; 309 | if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) { 310 | params.rightMargin = mConfig.getNavigationBarWidth(); 311 | } 312 | mStatusBarTintView.setLayoutParams(params); 313 | mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 314 | mStatusBarTintView.setVisibility(View.GONE); 315 | decorViewGroup.addView(mStatusBarTintView); 316 | } 317 | 318 | private void setupNavBarView(Context context, ViewGroup decorViewGroup) { 319 | mNavBarTintView = new View(context); 320 | LayoutParams params; 321 | if (mConfig.isNavigationAtBottom()) { 322 | params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight()); 323 | params.gravity = Gravity.BOTTOM; 324 | } else { 325 | params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT); 326 | params.gravity = Gravity.RIGHT; 327 | } 328 | mNavBarTintView.setLayoutParams(params); 329 | mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); 330 | mNavBarTintView.setVisibility(View.GONE); 331 | decorViewGroup.addView(mNavBarTintView); 332 | } 333 | 334 | /** 335 | * Class which describes system bar sizing and other characteristics for the current 336 | * device configuration. 337 | */ 338 | public static class SystemBarConfig { 339 | 340 | private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; 341 | private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; 342 | private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; 343 | private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; 344 | private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; 345 | 346 | private final boolean mTranslucentStatusBar; 347 | private final boolean mTranslucentNavBar; 348 | private final int mStatusBarHeight; 349 | private final int mActionBarHeight; 350 | private final boolean mHasNavigationBar; 351 | private final int mNavigationBarHeight; 352 | private final int mNavigationBarWidth; 353 | private final boolean mInPortrait; 354 | private final float mSmallestWidthDp; 355 | 356 | private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) { 357 | Resources res = activity.getResources(); 358 | mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); 359 | mSmallestWidthDp = getSmallestWidthDp(activity); 360 | mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME); 361 | mActionBarHeight = getActionBarHeight(activity); 362 | mNavigationBarHeight = getNavigationBarHeight(activity); 363 | mNavigationBarWidth = getNavigationBarWidth(activity); 364 | mHasNavigationBar = (mNavigationBarHeight > 0); 365 | mTranslucentStatusBar = translucentStatusBar; 366 | mTranslucentNavBar = traslucentNavBar; 367 | } 368 | 369 | @TargetApi(14) 370 | private int getActionBarHeight(Context context) { 371 | int result = 0; 372 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 373 | TypedValue tv = new TypedValue(); 374 | context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true); 375 | result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); 376 | } 377 | return result; 378 | } 379 | 380 | @TargetApi(14) 381 | private int getNavigationBarHeight(Context context) { 382 | Resources res = context.getResources(); 383 | int result = 0; 384 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 385 | if (hasNavBar(context)) { 386 | String key; 387 | if (mInPortrait) { 388 | key = NAV_BAR_HEIGHT_RES_NAME; 389 | } else { 390 | key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME; 391 | } 392 | return getInternalDimensionSize(res, key); 393 | } 394 | } 395 | return result; 396 | } 397 | 398 | @TargetApi(14) 399 | private int getNavigationBarWidth(Context context) { 400 | Resources res = context.getResources(); 401 | int result = 0; 402 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 403 | if (hasNavBar(context)) { 404 | return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME); 405 | } 406 | } 407 | return result; 408 | } 409 | 410 | @TargetApi(14) 411 | private boolean hasNavBar(Context context) { 412 | Resources res = context.getResources(); 413 | int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android"); 414 | if (resourceId != 0) { 415 | boolean hasNav = res.getBoolean(resourceId); 416 | // check override flag (see static block) 417 | if ("1".equals(sNavBarOverride)) { 418 | hasNav = false; 419 | } else if ("0".equals(sNavBarOverride)) { 420 | hasNav = true; 421 | } 422 | return hasNav; 423 | } else { // fallback 424 | return !ViewConfiguration.get(context).hasPermanentMenuKey(); 425 | } 426 | } 427 | 428 | private int getInternalDimensionSize(Resources res, String key) { 429 | int result = 0; 430 | int resourceId = res.getIdentifier(key, "dimen", "android"); 431 | if (resourceId > 0) { 432 | result = res.getDimensionPixelSize(resourceId); 433 | } 434 | return result; 435 | } 436 | 437 | @SuppressLint("NewApi") 438 | private float getSmallestWidthDp(Activity activity) { 439 | DisplayMetrics metrics = new DisplayMetrics(); 440 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 441 | activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); 442 | } else { 443 | // TODO this is not correct, but we don't really care pre-kitkat 444 | activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 445 | } 446 | float widthDp = metrics.widthPixels / metrics.density; 447 | float heightDp = metrics.heightPixels / metrics.density; 448 | return Math.min(widthDp, heightDp); 449 | } 450 | 451 | /** 452 | * Should a navigation bar appear at the bottom of the screen in the current 453 | * device configuration? A navigation bar may appear on the right side of 454 | * the screen in certain configurations. 455 | * 456 | * @return True if navigation should appear at the bottom of the screen, False otherwise. 457 | */ 458 | public boolean isNavigationAtBottom() { 459 | return (mSmallestWidthDp >= 600 || mInPortrait); 460 | } 461 | 462 | /** 463 | * Get the height of the system status bar. 464 | * 465 | * @return The height of the status bar (in pixels). 466 | */ 467 | public int getStatusBarHeight() { 468 | return mStatusBarHeight; 469 | } 470 | 471 | /** 472 | * Get the height of the action bar. 473 | * 474 | * @return The height of the action bar (in pixels). 475 | */ 476 | public int getActionBarHeight() { 477 | return mActionBarHeight; 478 | } 479 | 480 | /** 481 | * Does this device have a system navigation bar? 482 | * 483 | * @return True if this device uses soft key navigation, False otherwise. 484 | */ 485 | public boolean hasNavigtionBar() { 486 | return mHasNavigationBar; 487 | } 488 | 489 | /** 490 | * Get the height of the system navigation bar. 491 | * 492 | * @return The height of the navigation bar (in pixels). If the device does not have 493 | * soft navigation keys, this will always return 0. 494 | */ 495 | public int getNavigationBarHeight() { 496 | return mNavigationBarHeight; 497 | } 498 | 499 | /** 500 | * Get the width of the system navigation bar when it is placed vertically on the screen. 501 | * 502 | * @return The width of the navigation bar (in pixels). If the device does not have 503 | * soft navigation keys, this will always return 0. 504 | */ 505 | public int getNavigationBarWidth() { 506 | return mNavigationBarWidth; 507 | } 508 | 509 | /** 510 | * Get the layout inset for any system UI that appears at the top of the screen. 511 | * 512 | * @param withActionBar True to include the height of the action bar, False otherwise. 513 | * @return The layout inset (in pixels). 514 | */ 515 | public int getPixelInsetTop(boolean withActionBar) { 516 | return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0); 517 | } 518 | 519 | /** 520 | * Get the layout inset for any system UI that appears at the bottom of the screen. 521 | * 522 | * @return The layout inset (in pixels). 523 | */ 524 | public int getPixelInsetBottom() { 525 | if (mTranslucentNavBar && isNavigationAtBottom()) { 526 | return mNavigationBarHeight; 527 | } else { 528 | return 0; 529 | } 530 | } 531 | 532 | /** 533 | * Get the layout inset for any system UI that appears at the right of the screen. 534 | * 535 | * @return The layout inset (in pixels). 536 | */ 537 | public int getPixelInsetRight() { 538 | if (mTranslucentNavBar && !isNavigationAtBottom()) { 539 | return mNavigationBarWidth; 540 | } else { 541 | return 0; 542 | } 543 | } 544 | 545 | } 546 | 547 | } 548 | 549 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/utils/TitleBarHelper.java: -------------------------------------------------------------------------------- 1 | package com.binioter.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | import com.binioter.R; 7 | import com.binioter.widget.TopTitleBar; 8 | 9 | public class TitleBarHelper { 10 | 11 | private Context mContext; 12 | private TopTitleBar mTopTitleBar; 13 | 14 | public TitleBarHelper(Context context, TopTitleBar titleBar) { 15 | this.mContext = context; 16 | 17 | this.mTopTitleBar = titleBar; 18 | } 19 | 20 | /** 21 | * decorate the titleBar,white 22 | * 初始化并开启沉浸模式 23 | */ 24 | 25 | public void init() { 26 | if (mTopTitleBar != null) { 27 | mTopTitleBar.setBackgroundResource(R.color.title_bar_color); 28 | mTopTitleBar.setLeftClickListener(mDefaultListener);// set default 29 | // listener 30 | mTopTitleBar.setMainTitleColor(mContext.getResources().getColor(R.color.title_color)); 31 | mTopTitleBar.setLeftImageResource(R.mipmap.btn_back_normal); 32 | mTopTitleBar.setDividerHeight(1); 33 | mTopTitleBar.setDividerColor(mContext.getResources().getColor(R.color.title_color)); 34 | mTopTitleBar.setLeftTextColor(mContext.getResources().getColor(R.color.title_color)); 35 | mTopTitleBar.setImmersive(true); 36 | } 37 | } 38 | 39 | private View.OnClickListener mDefaultListener = new View.OnClickListener() { 40 | @Override public void onClick(View v) { 41 | if (mContext != null) { 42 | Activity activity = (Activity) mContext; 43 | activity.finish(); 44 | } 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/widget/SwipeBackLayout.java: -------------------------------------------------------------------------------- 1 | package com.binioter.widget; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.support.v4.view.MotionEventCompat; 9 | import android.util.AttributeSet; 10 | import android.util.TypedValue; 11 | import android.view.MotionEvent; 12 | import android.view.VelocityTracker; 13 | import android.view.View; 14 | import android.view.ViewConfiguration; 15 | import android.view.ViewGroup; 16 | import android.view.Window; 17 | import android.view.animation.Interpolator; 18 | import android.widget.FrameLayout; 19 | import android.widget.Scroller; 20 | import com.binioter.R; 21 | import com.binioter.util.DensityUtil; 22 | 23 | /** 24 | *

滑动返回


25 | * 滑动返回:支持将Activity设置为向右滑返回;

原理

继承自FrameLayout
26 | * 将Activity中显示内容的View添加到到SwipeBackLayout的实例中,再将SwipeBackLayout的实例添加到Activity中.
27 | * 对SwipeBackLayout实例借助Scroller类调用ScrollTo方法来实现滑动显示内容的View.
28 | * Activity的背景会被设置为透明的,这样在显示内容的View滑动的过程中才可以显示出底层View. 另外还需要调用了 29 | * {@link #setBgTransparent()}将SwipeBackLayout的实例的背景设置为透明. 30 | */ 31 | public class SwipeBackLayout extends FrameLayout { 32 | 33 | private Activity mActivity; 34 | private View mContentView; 35 | private ViewGroup mRealContentView; 36 | private Scroller mScroller; 37 | private int mViewWidth; 38 | 39 | private int mTouchSlop; 40 | private static final int MARGIN_THRESHOLD = 24; // dips 41 | 42 | private float mLastMotionX; 43 | private float mLastMotionY; 44 | private float mDownX; 45 | private int mCurMotionX; 46 | 47 | private int mActivePointerId = INVALID_POINTER; 48 | private static final int INVALID_POINTER = -1; 49 | 50 | private boolean mIsSilding = false; 51 | private boolean mIsFinish = false; 52 | private boolean mIsSwipeBackEnabled = true; 53 | private boolean mIsScrolling = false; 54 | 55 | private int mMarginThreshold; 56 | 57 | private int mAlphaBgColor = 0; 58 | private Rect mColorRect = new Rect(); 59 | 60 | private VelocityTracker mVelocityTracker; 61 | private int mMinimumVelocity; 62 | private int mMaximumVelocity; 63 | private int mFlingDistance; 64 | private int mMoveDistance; 65 | private static final int MIN_DISTANCE_FOR_MOVE = 24; // dips 66 | private float mXVelocity; 67 | 68 | /** 69 | * SwipeLayout的构造函数 70 | * 71 | * @param context 72 | */ 73 | public SwipeBackLayout(Context context) { 74 | super(context); 75 | init(context); 76 | } 77 | 78 | /** 79 | * SwipeLayout的构造函数 80 | * 81 | * @param context 82 | * @param attrs 83 | */ 84 | public SwipeBackLayout(Context context, AttributeSet attrs) { 85 | super(context, attrs); 86 | init(context); 87 | } 88 | 89 | /** 90 | * SwipeLayout的构造函数 91 | * 92 | * @param context 93 | * @param attrs 94 | * @param defStyle 95 | */ 96 | public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) { 97 | super(context, attrs, defStyle); 98 | init(context); 99 | } 100 | 101 | /** 102 | * 实例化一些需要的对象实例和参数 103 | * 104 | * @param context 105 | */ 106 | private void init(Context context) { 107 | mMarginThreshold = (int) TypedValue.applyDimension( 108 | TypedValue.COMPLEX_UNIT_DIP, MARGIN_THRESHOLD, getResources() 109 | .getDisplayMetrics()); 110 | mScroller = new Scroller(context, new MyAccelerateInterpolator(1.5f)); 111 | mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2; 112 | mMaximumVelocity = ViewConfiguration.getMaximumFlingVelocity(); 113 | mMinimumVelocity = ViewConfiguration.getMinimumFlingVelocity(); 114 | final float density = context.getResources().getDisplayMetrics().density; 115 | mMoveDistance = (int) (MIN_DISTANCE_FOR_MOVE * density); 116 | int deviceWidth = DensityUtil.getEquipmentWidth(context); 117 | mFlingDistance = deviceWidth / 4; 118 | } 119 | 120 | /** 121 | * @param activity 122 | */ 123 | public void attachToActivity(Activity activity) { 124 | try { 125 | mActivity = activity; 126 | 127 | Window window = activity.getWindow(); 128 | window.setBackgroundDrawable(new ColorDrawable(0)); 129 | 130 | ViewGroup decor = (ViewGroup) window.getDecorView(); 131 | mRealContentView = (ViewGroup) decor.getChildAt(0); 132 | decor.removeView(mRealContentView); 133 | mRealContentView.setClickable(true); 134 | addView(mRealContentView); 135 | mContentView = (View) mRealContentView.getParent(); 136 | decor.addView(this); 137 | } catch (Exception e) { 138 | mIsSwipeBackEnabled = false; 139 | } 140 | } 141 | 142 | @Override 143 | protected void dispatchDraw(Canvas canvas) { 144 | super.dispatchDraw(canvas); 145 | if (mContentView != null) { 146 | 147 | int left = 0; 148 | int right = mCurMotionX; 149 | int top = 0; 150 | int bottom = mContentView.getBottom(); 151 | 152 | mColorRect.top = top; 153 | mColorRect.bottom = bottom; 154 | mColorRect.left = left; 155 | mColorRect.right = right; 156 | canvas.clipRect(mColorRect); 157 | 158 | if (mViewWidth != 0) { 159 | mAlphaBgColor = 100 - (int) (((float) (-mCurMotionX) / (float) mViewWidth) * 120); 160 | } 161 | 162 | if (mAlphaBgColor > 100) { 163 | mAlphaBgColor = 100; 164 | } 165 | 166 | if (mIsFinish) { 167 | mAlphaBgColor = 0; 168 | } 169 | 170 | if (mAlphaBgColor < 0) { 171 | mAlphaBgColor = 0; 172 | } 173 | 174 | canvas.drawARGB(mAlphaBgColor, 0, 0, 0); 175 | } 176 | } 177 | 178 | /** 179 | * 事件拦截操作 180 | */ 181 | @Override 182 | public boolean onInterceptTouchEvent(MotionEvent event) { 183 | 184 | if (!mIsSwipeBackEnabled) { 185 | return super.onInterceptTouchEvent(event); 186 | } 187 | 188 | if (mIsFinish || mIsScrolling) { 189 | return super.onInterceptTouchEvent(event); 190 | } 191 | 192 | final int action = event.getAction() & MotionEventCompat.ACTION_MASK; 193 | 194 | if (action == MotionEvent.ACTION_CANCEL 195 | || action == MotionEvent.ACTION_UP) { 196 | endDrag(); 197 | return super.onInterceptTouchEvent(event); 198 | } 199 | 200 | switch (action) { 201 | case MotionEvent.ACTION_DOWN: 202 | 203 | int index = MotionEventCompat.getActionIndex(event); 204 | mActivePointerId = MotionEventCompat.getPointerId(event, index); 205 | 206 | if (isInvalidEvent(event, index, mActivePointerId)) { 207 | break; 208 | } 209 | 210 | mLastMotionX = MotionEventCompat.getX(event, index); 211 | mLastMotionY = MotionEventCompat.getY(event, index); 212 | mDownX = MotionEventCompat.getX(event, index); 213 | 214 | break; 215 | case MotionEvent.ACTION_MOVE: 216 | 217 | determineDrag(event); 218 | 219 | break; 220 | } 221 | 222 | return mIsSilding; 223 | } 224 | 225 | @Override 226 | public boolean onTouchEvent(MotionEvent event) { 227 | 228 | if (mIsFinish || mIsScrolling) { 229 | return super.onTouchEvent(event); 230 | } 231 | 232 | if (mVelocityTracker == null) { 233 | mVelocityTracker = VelocityTracker.obtain(); 234 | } 235 | mVelocityTracker.addMovement(event); 236 | 237 | switch (event.getAction() & MotionEventCompat.ACTION_MASK) { 238 | case MotionEvent.ACTION_DOWN: 239 | 240 | completeScroll(); 241 | 242 | int index = MotionEventCompat.getActionIndex(event); 243 | mActivePointerId = MotionEventCompat.getPointerId(event, index); 244 | mLastMotionX = event.getX(); 245 | mDownX = MotionEventCompat.getX(event, index); 246 | 247 | break; 248 | case MotionEvent.ACTION_MOVE: 249 | 250 | if (!mIsSilding) { 251 | determineDrag(event); 252 | } 253 | 254 | if (mIsSilding) { 255 | final int activePointerIndex = getPointerIndex(event, 256 | mActivePointerId); 257 | 258 | if (isInvalidEvent(event, activePointerIndex, mActivePointerId)) { 259 | break; 260 | } 261 | 262 | final float x = MotionEventCompat.getX(event, 263 | activePointerIndex); 264 | final float deltaX = mLastMotionX - x; 265 | mLastMotionX = x; 266 | float oldScrollX = getScrollX(); 267 | float scrollX = oldScrollX + deltaX; 268 | final float leftBound = -mViewWidth; 269 | final float rightBound = 0; 270 | if (scrollX < leftBound) { 271 | scrollX = leftBound; 272 | } else if (scrollX > rightBound) { 273 | scrollX = rightBound; 274 | } 275 | mLastMotionX += scrollX - (int) scrollX; 276 | mCurMotionX = (int) scrollX; 277 | mContentView.scrollTo((int) scrollX, getScrollY()); 278 | } 279 | 280 | break; 281 | case MotionEvent.ACTION_UP: 282 | 283 | final VelocityTracker velocityTracker = mVelocityTracker; 284 | velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 285 | mXVelocity = velocityTracker.getXVelocity(); 286 | 287 | int diffX = getDiffX(event); 288 | 289 | endDrag(); 290 | 291 | if (Math.abs(mXVelocity) > mMinimumVelocity && diffX > mFlingDistance) { 292 | if (mXVelocity > 0) { 293 | mIsFinish = true; 294 | scrollRight(); 295 | } else { 296 | scrollOrigin(); 297 | mIsFinish = false; 298 | } 299 | return true; 300 | } 301 | 302 | if (mContentView.getScrollX() <= -mViewWidth / 2) { 303 | mIsFinish = true; 304 | scrollRight(); 305 | } else { 306 | scrollOrigin(); 307 | mIsFinish = false; 308 | } 309 | break; 310 | 311 | case MotionEvent.ACTION_CANCEL: 312 | releaseVelocityTracker(); 313 | break; 314 | } 315 | 316 | return super.onTouchEvent(event); 317 | } 318 | 319 | private void determineDrag(MotionEvent ev) { 320 | final int activePointerId = mActivePointerId; 321 | final int pointerIndex = getPointerIndex(ev, activePointerId); 322 | 323 | if (isInvalidEvent(ev, pointerIndex, activePointerId)) { 324 | return; 325 | } 326 | 327 | final float x = MotionEventCompat.getX(ev, pointerIndex); 328 | final float dx = x - mLastMotionX; 329 | final float xDiff = Math.abs(dx); 330 | final float y = MotionEventCompat.getY(ev, pointerIndex); 331 | final float dy = y - mLastMotionY; 332 | final float yDiff = Math.abs(dy); 333 | if (dx > 0 && xDiff > mMoveDistance && xDiff > yDiff) { 334 | mIsSilding = true; 335 | mLastMotionX = x; 336 | mLastMotionY = y; 337 | } 338 | } 339 | 340 | private int getDiffX(MotionEvent ev) { 341 | final int activePointerId = mActivePointerId; 342 | final int pointerIndex = getPointerIndex(ev, activePointerId); 343 | 344 | if (isInvalidEvent(ev, pointerIndex, activePointerId)) { 345 | return 0; 346 | } 347 | 348 | final float x = MotionEventCompat.getX(ev, pointerIndex); 349 | final float dx = x - mDownX; 350 | final float xDiff = Math.abs(dx); 351 | return (int) xDiff; 352 | } 353 | 354 | private void endDrag() { 355 | mIsSilding = false; 356 | mActivePointerId = INVALID_POINTER; 357 | releaseVelocityTracker(); 358 | } 359 | 360 | private boolean isInvalidEvent(MotionEvent event, int pointerIndex, int pointerId) { 361 | 362 | if (event == null) { 363 | return true; 364 | } 365 | 366 | if (pointerId == INVALID_POINTER || pointerIndex == INVALID_POINTER) { 367 | return true; 368 | } 369 | 370 | if (pointerIndex >= event.getPointerCount()) { 371 | return true; 372 | } 373 | 374 | return false; 375 | } 376 | 377 | @Override 378 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 379 | super.onLayout(changed, l, t, r, b); 380 | if (changed) { 381 | mViewWidth = this.getWidth(); 382 | } 383 | } 384 | 385 | private int getPointerIndex(MotionEvent ev, int id) { 386 | int activePointerIndex = MotionEventCompat.findPointerIndex(ev, id); 387 | if (activePointerIndex == -1) 388 | mActivePointerId = INVALID_POINTER; 389 | return activePointerIndex; 390 | } 391 | 392 | /** 393 | * 滚动出界面 394 | */ 395 | private void scrollRight() { 396 | mIsScrolling = true; 397 | final int delta = (mViewWidth + mContentView.getScrollX()); 398 | mScroller.startScroll(mContentView.getScrollX(), 0, -delta + 1, 0); 399 | postInvalidate(); 400 | } 401 | 402 | /** 403 | * 滚动到起始位置 404 | */ 405 | private void scrollOrigin() { 406 | mIsScrolling = true; 407 | int delta = mContentView.getScrollX(); 408 | mScroller.startScroll(mContentView.getScrollX(), 0, -delta, 0); 409 | postInvalidate(); 410 | } 411 | 412 | private void completeScroll() { 413 | boolean needPopulate = mIsScrolling; 414 | if (needPopulate) { 415 | mScroller.abortAnimation(); 416 | int oldX = getScrollX(); 417 | int oldY = getScrollY(); 418 | int x = mScroller.getCurrX(); 419 | int y = mScroller.getCurrY(); 420 | if (oldX != x || oldY != y) { 421 | mContentView.scrollTo(x, y); 422 | } 423 | } 424 | mIsScrolling = false; 425 | } 426 | 427 | @Override 428 | public void computeScroll() { 429 | if (!mScroller.isFinished() && mScroller.computeScrollOffset()) { 430 | 431 | int oldX = getScrollX(); 432 | int oldY = getScrollY(); 433 | int x = mScroller.getCurrX(); 434 | int y = mScroller.getCurrY(); 435 | 436 | if (oldX != x || oldY != y) { 437 | mContentView.scrollTo(x, y); 438 | } 439 | 440 | invalidate(); 441 | } 442 | 443 | if (mScroller.isFinished() && mIsFinish) { 444 | mActivity.finish(); 445 | mActivity.overridePendingTransition(0, 0); 446 | } 447 | 448 | if (mScroller.isFinished()) { 449 | completeScroll(); 450 | } 451 | } 452 | 453 | private void releaseVelocityTracker() { 454 | if (mVelocityTracker != null) { 455 | mVelocityTracker.clear(); 456 | mVelocityTracker.recycle(); 457 | mVelocityTracker = null; 458 | } 459 | } 460 | 461 | /** 462 | * 是否滑动返回打开 463 | * 464 | * @return 465 | */ 466 | public boolean isSwipeBackEnabled() { 467 | return mIsSwipeBackEnabled; 468 | } 469 | 470 | /** 471 | * 设置滑动返回的开关 472 | * 473 | * @param isSwipeBackEnabled 474 | */ 475 | public void setSwipeBackEnabled(boolean isSwipeBackEnabled) { 476 | this.mIsSwipeBackEnabled = isSwipeBackEnabled; 477 | } 478 | 479 | /** 480 | * 设置背景为透明 481 | */ 482 | public void setBgTransparent() { 483 | if (mRealContentView != null) { 484 | mRealContentView.setBackgroundResource(R.color.transparent); 485 | } 486 | } 487 | 488 | private static class MyAccelerateInterpolator implements Interpolator { 489 | 490 | private final float mFactor; 491 | 492 | public MyAccelerateInterpolator(float factor) { 493 | mFactor = factor; 494 | } 495 | 496 | public float getInterpolation(float input) { 497 | float result = input * (float) mFactor; 498 | 499 | if (result > 0.9) { 500 | result = 1.0f; 501 | } 502 | 503 | return result; 504 | } 505 | } 506 | 507 | /** 508 | * 滑动返回的接口 509 | */ 510 | public interface SwipeControlInterface { 511 | /** 512 | * 打开滑动返回 513 | */ 514 | public void enableSwipeBack(); 515 | 516 | /** 517 | * 关闭滑动返回 518 | */ 519 | public void disableSwipeBack(); 520 | } 521 | } -------------------------------------------------------------------------------- /app/src/main/java/com/binioter/widget/TopTitleBar.java: -------------------------------------------------------------------------------- 1 | package com.binioter.widget; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.res.Resources; 6 | import android.content.res.TypedArray; 7 | import android.graphics.drawable.Drawable; 8 | import android.text.TextUtils; 9 | import android.util.AttributeSet; 10 | import android.view.Gravity; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ImageView; 14 | import android.widget.LinearLayout; 15 | import android.widget.TextView; 16 | import com.binioter.R; 17 | import java.util.ArrayList; 18 | import java.util.LinkedList; 19 | import java.util.List; 20 | 21 | /** 22 | * Created by zb on 2016/7/28. 23 | */ 24 | public class TopTitleBar extends LinearLayout implements View.OnClickListener { 25 | 26 | private static final String TAG = TopTitleBar.class.getSimpleName(); 27 | //private static final int DEFAULT_TITLE_BAR_HEIGHT = ; 28 | private static final int DEFAULT_LEFT_TEXT_SIZE = 16; 29 | private static final int DEFAULT_MAIN_TEXT_SIZE = 18; 30 | private static final int DEFAULT_SUB_TEXT_SIZE = 12; 31 | private static final int DEFAULT_ACTION_TEXT_SIZE = 16; 32 | 33 | private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; 34 | 35 | private Context mContext; 36 | 37 | private TextView mLeftText; 38 | private LinearLayout mRightLayout; 39 | private LinearLayout mCenterLayout; 40 | private TextView mCenterText; 41 | private TextView mSubTitleText; 42 | private View mDividerView; 43 | 44 | private boolean mImmersive; 45 | 46 | private int mScreenWidth; 47 | private int mStatusBarHeight; 48 | private int mActionPadding; 49 | private int mOutPadding; 50 | private int mMinSidePadding; 51 | private int mMainTextColor; 52 | private int mActionTextColor; 53 | private int mHeight; 54 | 55 | //中间布局是否一直居中,默认是 56 | private boolean isCenterAlways = true; 57 | 58 | /** titlebar中间的标题 */ 59 | private String mTitle = ""; 60 | 61 | /** titlebar背景色 */ 62 | private int mBackground = 0xf9f9f9; 63 | 64 | /** titlebar返回按钮图片 */ 65 | private int mBackIconRes = R.mipmap.btn_back_normal; 66 | 67 | /** titlebar返回按钮图片 */ 68 | private boolean mDividerVisible = true; 69 | 70 | /** action缓存列表,这里不用弱引用是因为action可能在函数体内部加入,退出函数作用域action就释放了 */ 71 | private final List mActionList = new ArrayList<>(); 72 | 73 | public TopTitleBar(Context context) { 74 | this(context, null); 75 | } 76 | 77 | public TopTitleBar(Context context, AttributeSet attrs) { 78 | this(context, attrs, 0); 79 | } 80 | 81 | public TopTitleBar(Context context, AttributeSet attrs, int defStyleAttr) { 82 | super(context, attrs, defStyleAttr); 83 | TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.TopTitleBar); 84 | mTitle = typedArray.getString(R.styleable.TopTitleBar_tb_title); 85 | mBackground = typedArray.getColor(R.styleable.TopTitleBar_tb_background, 86 | context.getResources().getColor(R.color.color_f9f9f9)); 87 | mBackIconRes = 88 | typedArray.getResourceId(R.styleable.TopTitleBar_tb_back_icon, R.mipmap.btn_back_normal); 89 | mDividerVisible = typedArray.getBoolean(R.styleable.TopTitleBar_tb_divider_visible, true); 90 | typedArray.recycle(); 91 | mContext = context; 92 | init(context); 93 | } 94 | 95 | private void init(Context context) { 96 | mScreenWidth = getResources().getDisplayMetrics().widthPixels; 97 | //若是浸没模式,则获取状态栏高度 98 | if (mImmersive) { 99 | mStatusBarHeight = getStatusBarHeight(); 100 | } else { 101 | mStatusBarHeight = 0; 102 | } 103 | mOutPadding = dip2px(15); //layout间margin 104 | mActionPadding = dip2px(5); //layout中控件间的padding 105 | mMinSidePadding = dip2px(15); //非恒定居中模式时,左右两边的最小间距 106 | mHeight = context.getResources().getDimensionPixelSize(R.dimen.title_height); 107 | initView(context); 108 | } 109 | 110 | private void initView(Context context) { 111 | setOrientation(HORIZONTAL); 112 | mLeftText = new TextView(context); 113 | mCenterLayout = new LinearLayout(context); 114 | mRightLayout = new LinearLayout(context); 115 | mDividerView = new View(context); 116 | 117 | LayoutParams layoutParams = 118 | new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 119 | 120 | //左布局初始化默认值 121 | setDefaultTextStyle(mLeftText); 122 | mLeftText.setTextSize(DEFAULT_LEFT_TEXT_SIZE); 123 | mLeftText.setPadding(mOutPadding, 0, 0, 0);//有文字或图片加入再重设padding 124 | //mLeftText.setCompoundDrawablePadding(mActionPadding);// add draw padding 125 | //左布局默认实现 126 | mLeftText.setOnClickListener(new View.OnClickListener() { 127 | @Override public void onClick(View view) { 128 | if (null != mContext && mContext instanceof Activity) { 129 | ((Activity) mContext).finish(); 130 | } 131 | } 132 | }); 133 | //中央布局初始化默认值,默认是主标题+子标题形式 134 | mCenterText = new TextView(context); 135 | mSubTitleText = new TextView(context); 136 | mCenterLayout.addView(mCenterText); 137 | mCenterLayout.addView(mSubTitleText); 138 | mCenterLayout.setGravity(Gravity.CENTER); 139 | setDefaultTextStyle(mCenterText); 140 | setDefaultTextStyle(mSubTitleText); 141 | mCenterText.setTextSize(DEFAULT_MAIN_TEXT_SIZE); 142 | mCenterText.setTextColor(context.getResources().getColor(R.color.color_394043)); 143 | mCenterText.setGravity(Gravity.CENTER); 144 | mSubTitleText.setTextSize(DEFAULT_SUB_TEXT_SIZE); 145 | mSubTitleText.setTextColor(context.getResources().getColor(R.color.color_394043)); 146 | mSubTitleText.setGravity(Gravity.CENTER); 147 | 148 | //右布局通过addAction动态添加 149 | mRightLayout.setPadding(mOutPadding, 0, 0, 0); 150 | 151 | //底部分割线 152 | mDividerView.setBackgroundColor(context.getResources().getColor(R.color.color_cccccc)); 153 | 154 | addView(mLeftText, layoutParams); 155 | addView(mCenterLayout); 156 | addView(mRightLayout, layoutParams); 157 | addView(mDividerView, new LayoutParams(LayoutParams.MATCH_PARENT, 1)); 158 | setBackgroundColor(context.getResources().getColor(R.color.color_6b7072)); 159 | setTitle(mTitle); 160 | setBackgroundColor(mBackground); 161 | setLeftImageResource(mBackIconRes); 162 | setDividerVisible(mDividerVisible); 163 | } 164 | 165 | /** 166 | * 开启沉浸式,状态栏的高度会增加到title bar的高度中 167 | * java代码中也需要进行设置 168 | */ 169 | public void setImmersive(boolean immersive) { 170 | mImmersive = immersive; 171 | if (mImmersive) { 172 | mStatusBarHeight = getStatusBarHeight(); 173 | } else { 174 | mStatusBarHeight = 0; 175 | } 176 | } 177 | 178 | public void setHeight(int height) { 179 | mHeight = height; 180 | setMeasuredDimension(getMeasuredWidth(), mHeight); 181 | } 182 | 183 | /** 184 | * 默认文字样式设置 185 | */ 186 | private void setDefaultTextStyle(TextView mTextView) { 187 | if (null != mContext) { 188 | mTextView.setTextColor(mContext.getResources().getColor(R.color.color_6b7072)); 189 | mTextView.setSingleLine(); 190 | mTextView.setGravity(Gravity.CENTER_VERTICAL); 191 | mTextView.setEllipsize(TextUtils.TruncateAt.END); 192 | } 193 | } 194 | 195 | /** 196 | * 左布局设置方法 197 | */ 198 | public void setLeftText(CharSequence title) { 199 | if (null == title) { 200 | return; 201 | } 202 | //设置文字和返回按钮间距 203 | mLeftText.setCompoundDrawablePadding(mActionPadding); 204 | mLeftText.setText(title); 205 | adjustLeftTextPadding(); 206 | } 207 | 208 | public void setLeftText(int resid) { 209 | //设置文字和返回按钮间距 210 | mLeftText.setCompoundDrawablePadding(mActionPadding); 211 | mLeftText.setText(resid); 212 | } 213 | 214 | public void setLeftImageResource(int resId) { 215 | mLeftText.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0); 216 | adjustLeftTextPadding(); 217 | } 218 | 219 | private void adjustLeftTextPadding() { 220 | mLeftText.setPadding(mOutPadding, 0, mOutPadding, 0); 221 | } 222 | 223 | public void setLeftClickListener(OnClickListener l) { 224 | mLeftText.setOnClickListener(l); 225 | } 226 | 227 | /** 228 | * @param left 单位dp 229 | * @param top 单位dp 230 | * @param right 单位dp 231 | * @param bottom 单位dp 232 | */ 233 | public void setLeftTextPadding(int left, int top, int right, int bottom) { 234 | mLeftText.setPadding(dip2px(left), dip2px(top), dip2px(right), dip2px(bottom)); 235 | } 236 | 237 | public void setLeftTextBackground(int resId) { 238 | mLeftText.setBackgroundResource(resId); 239 | } 240 | 241 | public void setLeftTextSize(float size) { 242 | mLeftText.setTextSize(size); 243 | } 244 | 245 | public void setLeftTextColor(int color) { 246 | mLeftText.setTextColor(color); 247 | } 248 | 249 | public void setLeftVisible(boolean visible) { 250 | mLeftText.setVisibility(visible ? View.VISIBLE : View.GONE); 251 | } 252 | 253 | /** 254 | * 设置文字标题,是否需要从新添加title,一般来说不需要,除非之前添加过centerview 255 | * 256 | * @param title 标题 257 | */ 258 | public void setTitle(CharSequence title) { 259 | setTitle(title, false); 260 | } 261 | 262 | /** 263 | * 中央布局设置方法 264 | * 265 | * @param title 标题 266 | * @param needReAdd 是否需要从新添加,一般来说不需要,除非之前添加过centerview 267 | */ 268 | public void setTitle(CharSequence title, boolean needReAdd) { 269 | if (null == title) { 270 | return; 271 | } 272 | if (needReAdd) { 273 | mCenterLayout.removeAllViews(); 274 | mCenterLayout.addView(mCenterText); 275 | mCenterLayout.addView(mSubTitleText); 276 | } 277 | //若用换行符分隔文字,则主标题和子标题竖直排列 278 | int index = title.toString().indexOf("\n"); 279 | if (index > 0) { 280 | setTitle(title.subSequence(0, index), title.subSequence(index + 1, title.length()), 281 | LinearLayout.VERTICAL); 282 | } else { 283 | //若用制表符分隔文字,则主标题和子标题水平排列 284 | index = title.toString().indexOf("\t"); 285 | if (index > 0) { 286 | setTitle(title.subSequence(0, index), " " + title.subSequence(index + 1, title.length()), 287 | LinearLayout.HORIZONTAL); 288 | } else { 289 | mCenterText.setText(title); 290 | mSubTitleText.setVisibility(View.GONE); 291 | } 292 | } 293 | } 294 | 295 | private void setTitle(CharSequence title, CharSequence subTitle, int orientation) { 296 | mCenterLayout.setOrientation(orientation); 297 | mCenterText.setText(title); 298 | mSubTitleText.setText(subTitle); 299 | mSubTitleText.setVisibility(View.VISIBLE); 300 | } 301 | 302 | public void setTitle(int resid) { 303 | setTitle(getResources().getString(resid)); 304 | } 305 | 306 | public void setCenterClickListener(OnClickListener l) { 307 | mCenterLayout.setOnClickListener(l); 308 | } 309 | 310 | public void setMainTitleSize(float size) { 311 | mCenterText.setTextSize(size); 312 | } 313 | 314 | public void setMainTitleColor(int color) { 315 | mCenterText.setTextColor(color); 316 | } 317 | 318 | public void setMainTitleBackground(int resid) { 319 | mCenterText.setBackgroundResource(resid); 320 | } 321 | 322 | public void setMainTitleVisible(boolean visible) { 323 | mCenterText.setVisibility(visible ? View.VISIBLE : View.GONE); 324 | } 325 | 326 | public void setSubTitleSize(float size) { 327 | mSubTitleText.setTextSize(size); 328 | } 329 | 330 | public void setSubTitleColor(int color) { 331 | mSubTitleText.setTextColor(color); 332 | } 333 | 334 | public void setSubTitleBackground(int resid) { 335 | mSubTitleText.setBackgroundResource(resid); 336 | } 337 | 338 | public void setSubTitleVisible(boolean visible) { 339 | mSubTitleText.setVisibility(visible ? View.VISIBLE : View.GONE); 340 | } 341 | 342 | /** 343 | * 中央布局设置自定义view,如搜索框等 344 | */ 345 | public void setCustomTitleView(View titleView) { 346 | LinearLayout.LayoutParams lp = 347 | new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 348 | ViewGroup.LayoutParams.WRAP_CONTENT); 349 | titleView.setLayoutParams(lp); 350 | mCenterLayout.removeAllViews(); 351 | mCenterLayout.addView(titleView); 352 | } 353 | 354 | /** 355 | * 设置中央布局控件可见性 356 | */ 357 | public void setCenterViewVisible(int visible) { 358 | mCenterLayout.setVisibility(visible); 359 | } 360 | 361 | /** 362 | * 设置中央布局不居中,紧凑排布 363 | */ 364 | public void setIsCenterAlways(boolean isCenterAlways) { 365 | this.isCenterAlways = isCenterAlways; 366 | invalidate(); 367 | } 368 | 369 | /** 370 | * 获得布局的真实宽度 371 | */ 372 | private int getRealWidth(View view) { 373 | int result = mMinSidePadding; 374 | if (null != view) { 375 | result = (view.getVisibility() == View.GONE) ? mMinSidePadding : view.getMeasuredWidth(); 376 | } 377 | return result; 378 | } 379 | 380 | /** 381 | * 底部分割线设置方法 382 | */ 383 | 384 | public void setDivider(int resId) { 385 | mDividerView.setBackgroundResource(resId); 386 | } 387 | 388 | public void setDividerColor(int color) { 389 | mDividerView.setBackgroundColor(color); 390 | } 391 | 392 | public void setDividerHeight(int dividerHeight) { 393 | mDividerView.getLayoutParams().height = dividerHeight; 394 | } 395 | 396 | public void setDividerVisible(boolean visible) { 397 | mDividerView.setVisibility(visible ? View.VISIBLE : View.GONE); 398 | } 399 | 400 | /** 401 | * 402 | */ 403 | /*public void setActionTextColor(int colorResId) { 404 | mActionTextColor = colorResId; 405 | }*/ 406 | @Override public void onClick(View view) { 407 | final Object tag = view.getTag(); 408 | if (tag instanceof Action) { 409 | final Action action = (Action) tag; 410 | action.performAction(view); 411 | } 412 | } 413 | 414 | /** 415 | * Adds a list of {@link Action}s. 416 | * 417 | * @param actionList the actions to add 418 | */ 419 | public void addActions(ActionList actionList) { 420 | int actions = actionList.size(); 421 | for (int i = 0; i < actions; i++) { 422 | addAction(actionList.get(i)); 423 | } 424 | } 425 | 426 | /** 427 | * Adds a new {@link Action}. 428 | * 429 | * @param action the action to add 430 | */ 431 | public View addAction(Action action) { 432 | final int index = mRightLayout.getChildCount(); 433 | return addAction(action, index); 434 | } 435 | 436 | /** 437 | * Adds a new {@link Action} at the specified index. 438 | * 439 | * @param action the action to add 440 | * @param index the position at which to add the action 441 | */ 442 | public View addAction(Action action, int index) { 443 | if (null == action) { 444 | return null; 445 | } 446 | mActionList.add(action); 447 | LinearLayout.LayoutParams params = 448 | new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 449 | View view = inflateAction(action); 450 | mRightLayout.addView(view, index, params); 451 | return view; 452 | } 453 | 454 | /** 455 | * Removes all action views from this action bar 456 | */ 457 | public void removeAllActions() { 458 | mRightLayout.removeAllViews(); 459 | } 460 | 461 | /** 462 | * Remove a action from the action bar. 463 | * 464 | * @param index position of action to remove 465 | */ 466 | public void removeActionAt(int index) { 467 | mRightLayout.removeViewAt(index); 468 | } 469 | 470 | /** 471 | * Remove a action from the action bar. 472 | * 473 | * @param action The action to remove 474 | */ 475 | public void removeAction(Action action) { 476 | int childCount = mRightLayout.getChildCount(); 477 | for (int i = 0; i < childCount; i++) { 478 | View view = mRightLayout.getChildAt(i); 479 | if (view != null) { 480 | final Object tag = view.getTag(); 481 | if (tag instanceof Action && tag.equals(action)) { 482 | mRightLayout.removeView(view); 483 | } 484 | } 485 | } 486 | } 487 | 488 | /** 489 | * Returns the number of actions currently registered with the action bar. 490 | * 491 | * @return action count 492 | */ 493 | public int getActionCount() { 494 | return mRightLayout.getChildCount(); 495 | } 496 | 497 | private View inflateAction(Action action) { 498 | View view = null; 499 | if (action instanceof ImageAction) { 500 | ImageView img = new ImageView(getContext()); 501 | img.setImageResource(action.getDrawable()); 502 | view = img; 503 | } else if (action instanceof TextAction) { 504 | TextView text = new TextView(getContext()); 505 | setDefaultTextStyle(text); 506 | text.setText(action.getText()); 507 | text.setTextSize(DEFAULT_ACTION_TEXT_SIZE); 508 | if (((TextAction) action).getColor() != -1) { 509 | text.setTextColor(((TextAction) action).getColor()); 510 | } 511 | view = text; 512 | } else if (action instanceof ViewAction) { 513 | view = ((ViewAction) action).getView(); 514 | } 515 | if (action.getBackground() != 0) { 516 | view.setBackgroundResource(action.getBackground()); 517 | } 518 | view.setPadding(0, 0, mOutPadding, 0); 519 | view.setTag(action); 520 | view.setOnClickListener(this); 521 | return view; 522 | } 523 | 524 | public View getViewByAction(Action action) { 525 | View view = findViewWithTag(action); 526 | return view; 527 | } 528 | 529 | /** 530 | * 设置右边第一个按钮图标 531 | * 532 | * @param drawable 图片资源 533 | */ 534 | public void setRightImage(Drawable drawable) { 535 | setRightImage(0, drawable); 536 | } 537 | 538 | /** 539 | * 设置右边按钮图标 540 | * 541 | * @param index 图标位置 542 | * @param drawable 图片资源 543 | */ 544 | public void setRightImage(int index, Drawable drawable) { 545 | Action action = mActionList.get(index); 546 | if (null != action) { 547 | View view = getViewByAction(action); 548 | if (null != view && view instanceof ImageView) { 549 | ImageView imageView = (ImageView) view; 550 | imageView.setImageDrawable(drawable); 551 | } 552 | } 553 | } 554 | 555 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 556 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 557 | int height; 558 | if (heightMode != MeasureSpec.EXACTLY) {// 没有指定高度 559 | height = mHeight + mStatusBarHeight; 560 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY); 561 | } else {// 指定后高度 562 | height = MeasureSpec.getSize(heightMeasureSpec) + mStatusBarHeight; 563 | } 564 | 565 | measureChild(mLeftText, widthMeasureSpec, heightMeasureSpec); 566 | measureChild(mRightLayout, widthMeasureSpec, heightMeasureSpec); 567 | 568 | if (isCenterAlways) { 569 | if (mLeftText.getMeasuredWidth() > mRightLayout.getMeasuredWidth()) { 570 | mCenterLayout.measure( 571 | MeasureSpec.makeMeasureSpec(mScreenWidth - 2 * mLeftText.getMeasuredWidth(), 572 | MeasureSpec.EXACTLY), heightMeasureSpec); 573 | } else { 574 | mCenterLayout.measure( 575 | MeasureSpec.makeMeasureSpec(mScreenWidth - 2 * mRightLayout.getMeasuredWidth(), 576 | MeasureSpec.EXACTLY), heightMeasureSpec); 577 | } 578 | } else { 579 | mCenterLayout.measure(MeasureSpec.makeMeasureSpec(mScreenWidth - 580 | getRealWidth(mLeftText) - 581 | getRealWidth(mRightLayout), MeasureSpec.EXACTLY), heightMeasureSpec); 582 | } 583 | 584 | measureChild(mDividerView, widthMeasureSpec, heightMeasureSpec); 585 | setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height); 586 | } 587 | 588 | @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { 589 | mLeftText.layout(0, mStatusBarHeight, mLeftText.getMeasuredWidth(), 590 | mLeftText.getMeasuredHeight() + mStatusBarHeight); 591 | mRightLayout.layout(mScreenWidth - mRightLayout.getMeasuredWidth(), mStatusBarHeight, 592 | mScreenWidth, mRightLayout.getMeasuredHeight() + mStatusBarHeight); 593 | 594 | if (isCenterAlways) { 595 | if (mLeftText.getMeasuredWidth() > mRightLayout.getMeasuredWidth()) { 596 | mCenterLayout.layout(mLeftText.getMeasuredWidth(), mStatusBarHeight, 597 | mScreenWidth - mLeftText.getMeasuredWidth(), getMeasuredHeight()); 598 | } else { 599 | mCenterLayout.layout(mRightLayout.getMeasuredWidth(), mStatusBarHeight, 600 | mScreenWidth - mRightLayout.getMeasuredWidth(), getMeasuredHeight()); 601 | } 602 | } else { 603 | mCenterLayout.layout(getRealWidth(mLeftText), mStatusBarHeight, 604 | mScreenWidth - getRealWidth(mRightLayout), getMeasuredHeight()); 605 | } 606 | 607 | mDividerView.layout(0, getMeasuredHeight() - mDividerView.getMeasuredHeight(), 608 | getMeasuredWidth(), getMeasuredHeight()); 609 | } 610 | 611 | private int dip2px(int dpValue) { 612 | final float scale = Resources.getSystem().getDisplayMetrics().density; 613 | return (int) (dpValue * scale + 0.5f); 614 | } 615 | 616 | /** 617 | * 计算状态栏高度高度 getStatusBarHeight 618 | */ 619 | public static int getStatusBarHeight() { 620 | return getInternalDimensionSize(Resources.getSystem(), STATUS_BAR_HEIGHT_RES_NAME); 621 | } 622 | 623 | private static int getInternalDimensionSize(Resources res, String key) { 624 | int result = 0; 625 | int resourceId = res.getIdentifier(key, "dimen", "android"); 626 | if (resourceId > 0) { 627 | result = res.getDimensionPixelSize(resourceId); 628 | } 629 | return result; 630 | } 631 | 632 | /** 633 | * A {@link LinkedList} that holds a list of {@link Action}s. 634 | */ 635 | @SuppressWarnings("serial") public static class ActionList extends LinkedList { 636 | } 637 | 638 | /** 639 | * Definition of an action that could be performed, along with a icon to 640 | * show. 641 | */ 642 | public interface Action { 643 | 644 | String getText(); 645 | 646 | int getDrawable(); 647 | 648 | void performAction(View view); 649 | 650 | int getBackground(); 651 | } 652 | 653 | public static class BaseAction implements Action { 654 | @Override public int getDrawable() { 655 | return 0; 656 | } 657 | 658 | @Override public void performAction(View view) { 659 | 660 | } 661 | 662 | @Override public String getText() { 663 | return null; 664 | } 665 | 666 | @Override public int getBackground() { 667 | return 0; 668 | } 669 | } 670 | 671 | public static class ImageAction extends BaseAction { 672 | 673 | private int mDrawable; 674 | 675 | public ImageAction(int drawable) { 676 | mDrawable = drawable; 677 | } 678 | 679 | @Override public int getDrawable() { 680 | return mDrawable; 681 | } 682 | } 683 | 684 | public static class TextAction extends BaseAction { 685 | 686 | final private String mText; 687 | private int mColor = -1; 688 | 689 | public TextAction(String text) { 690 | mText = text; 691 | } 692 | 693 | public TextAction(String text, int color) { 694 | mText = text; 695 | mColor = color; 696 | } 697 | 698 | @Override public String getText() { 699 | return mText; 700 | } 701 | 702 | public int getColor() { 703 | return mColor; 704 | } 705 | } 706 | 707 | /** 708 | * 低级接口,直接返回view 709 | */ 710 | public static class ViewAction extends BaseAction { 711 | 712 | private View mView; 713 | 714 | public ViewAction(View view) { 715 | mView = view; 716 | } 717 | 718 | public View getView() { 719 | return mView; 720 | } 721 | } 722 | } 723 | 724 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_common_dialog_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 20 | 21 | 22 |