封装的基础类----BaseActivity
需求要点:
- 显示进度的dialog;
- 自定义Actionbar;
- 返回按钮的处理;
- 是否显示状态栏;
- activity的管理;
- 自适应布局控件;
实现:
BaseActivity.java
public abstract class BaseActivity extends AppActivity implements DialogControl,
EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
private static final String TAG = "BaseActivity";
protected static final int REQUEST_CODE_SETTINGS = 101;
protected static final int RC_PHONE_AND_STORAGE = 201;
protected static final String[] PERMS_PHONE_AND_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE};
private Dialog mWaitDialog;
protected BaseAppBarCompat mAppBarCompat = new BaseAppBarCompat();
@Nullable
@Override
public AppBarConfig getAppBarConfig() {
return null;
}
@Override
public void onBackPressed() {
hideWaitDialog();
super.onBackPressed();
}
@Override
public void hideWaitDialog() {
try {
if (mWaitDialog != null) {
mWaitDialog.dismiss();
}
mWaitDialog = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public Dialog showWaitDialog() {
return showWaitDialog(R.string.wait_loading);
}
@Override
public Dialog showWaitDialog(int resid) {
return showWaitDialog(getString(resid));
}
@Override
public Dialog showWaitDialog(String text) {
if (mWaitDialog == null) {
mWaitDialog = DialogManager.getWaitDialog(this, text);
}
if (mWaitDialog != null) {
TextView textView = mWaitDialog.findViewById(R.id.tv_message);
textView.setText(text);
mWaitDialog.show();
}
return mWaitDialog;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onRationaleAccepted(int requestCode) {
}
@Override
public void onRationaleDenied(int requestCode) {
}
public class BaseAppBarCompat extends AppBarConfig.AppBarCompat {
TextView textViewTitle;
@SuppressLint("ResourceAsColor")
@Override
public void actionbar(@NonNull ActionBar actionbar) {
super.actionbar(actionbar);
// Configure the "Action Bar" here
// and set a common loading method to suit different needs
ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,
ActionBar.LayoutParams.MATCH_PARENT, Gravity.CENTER);
View view = LayoutInflater.from(BaseActivity.this).inflate(R.layout.action_bar_layout, null);
((TextView) (view.findViewById(R.id.tv_action_bar_title))).setText(setActionBarTitle() == null ? " " : setActionBarTitle());
textViewTitle = view.findViewById(R.id.tv_action_bar_title);
textViewTitle.setTextSize(setActionBarTitleSize());
view.findViewById(R.id.iv_action_bar_back).setOnClickListener(v -> actionBarBackOnClick());
TextView button = view.findViewById(R.id.btn_action_bar_title_on_right);
button.setVisibility(setActionBarRightVisibility());
button.setText(setActionBarRightText());
view.findViewById(R.id.btn_action_bar_title_on_right).setOnClickListener(v -> actionBarRightOnClick());
// ImageView imageView = view.findViewById(R.id.search_bar);
// imageView.setVisibility(setActionBarRightSearchVisibility());
// imageView.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// actionBarRightSearchOnClick();
// }
// });
// padding view
actionbar.setCustomView(view, lp);
// setting params
actionbar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
actionbar.setDisplayShowCustomEnabled(true);
actionbar.setDisplayShowHomeEnabled(false);
actionbar.setDisplayShowTitleEnabled(false);
}
public void setTextViewTitle(String title) {
textViewTitle.setText(title);
}
}
protected int setActionBarRightVisibility() {
return View.GONE;
}
protected float setActionBarTitleSize() {
return 22f;
}
// protected int setActionBarRightSearchVisibility() {
// return View.GONE;
// }
protected CharSequence setActionBarTitle() {
return null;
}
protected void actionBarBackOnClick() {
onBackPressed();
}
protected void actionBarRightOnClick() {
}
// protected void actionBarRightSearchOnClick() {
//
// }
protected CharSequence setActionBarRightText() {
return null;
}
protected void toast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
2. action_bar_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl_action_bar_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@color/color_000000">
<ImageView
android:id="@+id/iv_action_bar_back"
android:layout_width="@dimen/px60"
android:layout_height="match_parent"
android:src="@drawable/ic_back_white" />
<TextView
android:id="@+id/tv_action_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/color_ffffff"
android:textSize="@dimen/font_22"
tools:text="标题" />
<TextView
android:id="@+id/tv_action_bar_title_on_lift"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/px80"
android:textColor="@color/color_ffffff"
android:textSize="@dimen/font_22"
android:visibility="gone"
tools:text="标题"
tools:visibility="visible" />
<TextView
android:id="@+id/btn_action_bar_title_on_right"
android:layout_width="wrap_content"
android:layout_height="@dimen/px80"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/px20"
android:textColor="@color/color_ffffff"
android:textSize="@dimen/font_14"
android:visibility="gone"
android:text="提交"
tools:visibility="visible"/>
<ImageView
android:id="@+id/search_bar"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:visibility="gone"
android:layout_marginEnd="10dp"
android:src="@drawable/actionbar_search_icon" />
</RelativeLayout>
3. AppActivity.java
public abstract class AppActivity extends AppCompatActivity
implements IActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
private static final String TAG = "AppActivity";
private Unbinder unbinder;
@SuppressWarnings("unchecked")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppBarConfig appBarConfig = getAppBarConfig();
if (appBarConfig == null) {
//turning off the title at the top of the screen if not config AppBar
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
}
//does not mean that the method (setContentView) will must be called after this method called
onBeforeSetContentView();
int layoutResID = getLayoutResID();
if (layoutResID != 0) {
setContentView(layoutResID);
//butterKnife depends on contentView
unbinder = ButterKnife.bind(this);
//Toolbar depends on contentView
if (appBarConfig != null) {
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
appBarConfig.actionbar(supportActionBar);
}
}
//custom init content view
initContentView(savedInstanceState);
} else {
//Actionbar does not depends on contentView
if (appBarConfig != null) {
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
appBarConfig.actionbar(supportActionBar);
}
}
}
ActivityCollector.addActivity(this);
//Decoupled by dependency injection
ARouter.getInstance().inject(this);
initData(savedInstanceState);
}
//AutoLayout(Option)
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
View autoView = AutoLayoutManager.convertToAutoView(name, context, attrs);
return autoView == null ? super.onCreateView(parent, name, context, attrs) : autoView;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (unbinder != null && unbinder != Unbinder.EMPTY) unbinder.unbind();
unbinder = null;
ActivityCollector.removeActivity(this);
}
}
4. IActivity.java
public interface IActivity {
void onBeforeSetContentView();
@CheckResult
@LayoutRes
int getLayoutResID();
void initContentView(@Nullable Bundle savedInstanceState);
void initData(@Nullable Bundle savedInstanceState);
@Nullable
AppBarConfig getAppBarConfig();
}
5. ActivityCollector.java存储所有的activity,第3步中调用
public class ActivityCollector {
public static List<Activity> activitys = new ArrayList<Activity>();
/**
* 向List中添加一个活动
* @param activity 活动
*/
public static void addActivity( Activity activity ){
activitys.add(activity);
}
/**
* 从List中移除活动
* @param activity 活动
*/
public static void removeActivity( Activity activity ){
activitys.remove(activity);
}
/**
* 将List中存储的活动全部销毁掉
*/
public static void finishAll(){
for ( Activity activity : activitys ) {
if ( !activity.isFinishing() ) {
activity.finish();
}
}
}
}
6. DialogControl.java 第3步中调用
public interface DialogControl {
/**
* hideWaitDialog
*/
void hideWaitDialog();
/**
* showWaitDialog
* @return
*/
Dialog showWaitDialog();
/**
* showWaitDialog
* @param resid
* @return
*/
Dialog showWaitDialog(int resid);
/**
* showWaitDialog
* @param text
* @return
*/
Dialog showWaitDialog(String text);
}
7. 使用:
public class OfficeAddActivity extends BaseActivity {
private static final String TAG = "OfficeAddActivity";
private Context mContext;
@Override
public void onBeforeSetContentView() {
//设置状态栏颜色
StatusBarUtil.translucent(this, ContextCompat.getColor(this, R.color.color_0a5fb6));
}
@Override
public int getLayoutResID() {
return R.layout.activity_office_add;
}
@Override
protected CharSequence setActionBarTitle() {
return "添加单位";
}
@Nullable
@Override
public AppBarConfig getAppBarConfig() {
return mAppBarCompat;
}
@Override
public int setActionBarRightVisibility() {
return View.VISIBLE;
}
@Override
public CharSequence setActionBarRightText() {
return "提交";
}
@Override
protected void actionBarRightOnClick() {
addOfficeData();
}
@Override
public void initContentView(@Nullable Bundle savedInstanceState) {
}
@Override
public void initData(@Nullable Bundle savedInstanceState) {
}
}
8. 状态栏StatusBarUtil.java
public class StatusBarUtil {
private final static int STATUSBAR_TYPE_DEFAULT = 0;
private final static int STATUSBAR_TYPE_MIUI = 1;
private final static int STATUSBAR_TYPE_FLYME = 2;
private final static int STATUSBAR_TYPE_ANDROID6 = 3; // Android 6.0
private static @StatusBarType
int mStatusBarType = STATUSBAR_TYPE_DEFAULT;
private final static int STATIC_BAR_COLOR_MARK = -1;
public static void translucent(Activity activity) {
translucent(activity, STATIC_BAR_COLOR_MARK);
}
/**
* 沉浸式状态栏
* 支持 4.4 以上版本的 MIUI 和 Flyme,以及 5.0 以上版本的其他 Android
*
* @param activity
*/
@TargetApi(19)
public static void translucent(Activity activity, @ColorInt int colorOn5x) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
// 版本小于4.4,绝对不考虑沉浸式
return;
}
// 小米和魅族4.4 以上版本支持沉浸式
if (OsUtil.isFlyme() || OsUtil.isMIUI()) {
Window window = activity.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams
.FLAG_TRANSLUCENT_STATUS);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View
.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// android 6以后可以改状态栏字体颜色,因此可以自行设置为透明
// ZUK Z1是个另类,自家应用可以实现字体颜色变色,但没开放接口
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (colorOn5x == STATIC_BAR_COLOR_MARK) {
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.setStatusBarColor(colorOn5x);
}
} else {
// android 5不能修改状态栏字体颜色,因此直接用FLAG_TRANSLUCENT_STATUS,nexus表现为半透明
// update: 部分手机运用FLAG_TRANSLUCENT_STATUS时背景不是半透明而是没有背景了。。。。。
// window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 采取setStatusBarColor的方式,部分机型不支持,那就纯黑了,保证状态栏图标可见
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(colorOn5x);
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// android4.4的默认是从上到下黑到透明,我们的背景是白色,很难看,因此只做魅族和小米的
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
SystemBarTintManager tintManager = new SystemBarTintManager(activity);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintColor(colorOn5x);
}
}
/**
* 设置状态栏黑色字体图标,
* 支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android
*
* @param activity 需要被处理的 Activity
*/
public static boolean setStatusBarLightMode(Activity activity) {
if (mStatusBarType != STATUSBAR_TYPE_DEFAULT) {
return setStatusBarLightMode(activity, mStatusBarType);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isMIUICustomStatusBarLightModeImpl() && MIUISetStatusBarLightMode(activity.getWindow(), true)) {
mStatusBarType = STATUSBAR_TYPE_MIUI;
return true;
} else if (FlymeSetStatusBarLightMode(activity.getWindow(), true)) {
mStatusBarType = STATUSBAR_TYPE_FLYME;
return true;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Android6SetStatusBarLightMode(activity.getWindow(), true);
mStatusBarType = STATUSBAR_TYPE_ANDROID6;
return true;
}
}
return false;
}
/**
* 已知系统类型时,设置状态栏黑色字体图标。
* 支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android
*
* @param activity 需要被处理的 Activity
* @param type StatusBar 类型,对应不同的系统
*/
private static boolean setStatusBarLightMode(Activity activity, @StatusBarType int type) {
if (type == STATUSBAR_TYPE_MIUI) {
return MIUISetStatusBarLightMode(activity.getWindow(), true);
} else if (type == STATUSBAR_TYPE_FLYME) {
return FlymeSetStatusBarLightMode(activity.getWindow(), true);
} else if (type == STATUSBAR_TYPE_ANDROID6) {
return Android6SetStatusBarLightMode(activity.getWindow(), true);
}
return false;
}
/**
* 设置状态栏白色字体图标
* 支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android
*/
public static boolean setStatusBarDarkMode(Activity activity) {
if (mStatusBarType == STATUSBAR_TYPE_DEFAULT) {
// 默认状态,不需要处理
return true;
}
if (mStatusBarType == STATUSBAR_TYPE_MIUI) {
return MIUISetStatusBarLightMode(activity.getWindow(), false);
} else if (mStatusBarType == STATUSBAR_TYPE_FLYME) {
return FlymeSetStatusBarLightMode(activity.getWindow(), false);
} else if (mStatusBarType == STATUSBAR_TYPE_ANDROID6) {
return Android6SetStatusBarLightMode(activity.getWindow(), false);
}
return true;
}
@TargetApi(23)
private static int changeStatusBarModeRetainFlag(Window window, int out) {
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
out = retainSystemUiFlag(window, out, View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
return out;
}
public static int retainSystemUiFlag(Window window, int out, int type) {
int now = window.getDecorView().getSystemUiVisibility();
if ((now & type) == type) {
out |= type;
}
return out;
}
/**
* 设置状态栏字体图标为深色,Android 6
*
* @param window 需要设置的窗口
* @param light 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
@TargetApi(23)
private static boolean Android6SetStatusBarLightMode(Window window, boolean light) {
View decorView = window.getDecorView();
int systemUi = light ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
systemUi = changeStatusBarModeRetainFlag(window, systemUi);
decorView.setSystemUiVisibility(systemUi);
return true;
}
/**
* 设置状态栏字体图标为深色,需要 MIUIV6 以上
*
* @param window 需要设置的窗口
* @param dark 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回 true
*/
@SuppressWarnings("unchecked")
public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
boolean result = false;
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
if (dark) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
} else {
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
}
result = true;
} catch (Exception ignored) {
}
}
return result;
}
/**
* 更改状态栏图标、文字颜色的方案是否是MIUI自家的, MIUI9之后用回Android原生实现
* 见小米开发文档说明:https://dev.mi.com/console/doc/detail?pId=1159
*/
private static boolean isMIUICustomStatusBarLightModeImpl() {
return OsUtil.isMIUIV5() || OsUtil.isMIUIV6() ||
OsUtil.isMIUIV7() || OsUtil.isMIUIV8();
}
/**
* 设置状态栏图标为深色和魅族特定的文字风格
* 可以用来判断是否为 Flyme 用户
*
* @param window 需要设置的窗口
* @param dark 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
boolean result = false;
if (window != null) {
try {
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class
.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class
.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception ignored) {
}
}
return result;
}
@IntDef({STATUSBAR_TYPE_DEFAULT, STATUSBAR_TYPE_MIUI, STATUSBAR_TYPE_FLYME, STATUSBAR_TYPE_ANDROID6})
@Retention(RetentionPolicy.SOURCE)
private @interface StatusBarType {
}
}
9. 自适应屏幕控件AutoLayoutManager.java,第3步使用
class AutoLayoutManager {
private static final String LAYOUT_LINEARLAYOUT = "LinearLayout";
private static final String LAYOUT_FRAMELAYOUT = "FrameLayout";
private static final String LAYOUT_RELATIVELAYOUT = "RelativeLayout";
private static int USE_AUTOLAYOUT = -1;
private AutoLayoutManager() {
throw new IllegalStateException("not instance for you");
}
@Nullable
static View convertToAutoView(String name, Context context, AttributeSet attrs) {
if (USE_AUTOLAYOUT == -1) {
USE_AUTOLAYOUT = 1;
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo;
try {
applicationInfo = packageManager.getApplicationInfo(context
.getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo == null || applicationInfo.metaData == null
|| !applicationInfo.metaData.containsKey("design_width")
|| !applicationInfo.metaData.containsKey("design_height")) {
USE_AUTOLAYOUT = 0;
}
} catch (PackageManager.NameNotFoundException e) {
USE_AUTOLAYOUT = 0;
}
}
if (USE_AUTOLAYOUT == 0) {
return null;
}
View view;
switch (name) {
case LAYOUT_FRAMELAYOUT:
view = new AutoFrameLayout(context, attrs);
break;
case LAYOUT_LINEARLAYOUT:
view = new AutoLinearLayout(context, attrs);
break;
case LAYOUT_RELATIVELAYOUT:
view = new AutoRelativeLayout(context, attrs);
break;
default:
view = null;
}
return view;
}
}