package com.idrv.coach.ui; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.os.Bundle; import android.support.annotation.MenuRes; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.PopupMenu; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewConfiguration; import android.view.Window; import android.view.WindowManager; import com.idrv.coach.R; import com.idrv.coach.ZjbApplication; import com.idrv.coach.data.manager.RxBusManager; import com.idrv.coach.ui.fragment.BaseFragment; import com.idrv.coach.ui.view.compat.StatusBarCompat; import com.idrv.coach.ui.widget.BaseLayout; import com.idrv.coach.ui.widget.SwipeBackLayout; import com.idrv.coach.ui.widget.ToolbarLayout; import com.idrv.coach.utils.SystemBarUtil; import com.idrv.coach.utils.ViewLayoutUtil; import com.idrv.coach.utils.handler.WeakHandler; import com.idrv.coach.utils.helper.DialogHelper; import com.idrv.coach.utils.helper.UIHelper; import com.tendcloud.tenddata.TCAgent; import java.lang.reflect.Field; import java.lang.reflect.Method; import rx.Subscription; import rx.subscriptions.CompositeSubscription; /** * time: 15/6/9 * description:activity的基础类,理论上所有的activity都必须继承自本activity * * @author sunjianfei */ public abstract class BaseActivity<ViewModel> extends AppCompatActivity implements BaseLayout.OnBaseLayoutClickListener, DialogInterface.OnCancelListener { protected BaseLayout mBaseLayout; protected ToolbarLayout mToolbarLayout; protected Dialog mProgressDialog; protected boolean mTranslucentStatusEnable = false; protected boolean mTranslucentNavigationEnable = false; protected boolean mDestroyed = false; protected ViewModel mViewModel; protected CompositeSubscription mCompositeSubscription; protected SwipeBackLayout mSwipeBackLayout; protected boolean mIsInitialized; protected PopupMenu mPopupMenu; protected int mMenuRes; protected boolean mIsPopupMenuShow; private BaseFragment mBaseFragment; protected WeakHandler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { initWindowView(); super.onCreate(savedInstanceState); mCompositeSubscription = new CompositeSubscription(); //1.将背景设置为透明 setOverflowShowingAlways(); mDestroyed = false; ZjbApplication.addActivity(this); StatusBarCompat.compat(this, getStatusBarColor()); } public void setBackground(int resId) { mToolbarLayout.setBackground(resId); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); if (mTranslucentStatusEnable) { translucentStatusBar(); } if (mTranslucentNavigationEnable) { translucentNavigationBar(); } mSwipeBackLayout.attachToActivity(this); } private void initWindowView() { Window window = getWindow(); window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { window.getDecorView().setBackground(null); } else { window.getDecorView().setBackgroundDrawable(null); } } /** * Set action bar overflow showing always, avoid it's not showing on some phones. */ private void setOverflowShowingAlways() { try { ViewConfiguration config = ViewConfiguration.get(this); Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); menuKeyField.setAccessible(true); menuKeyField.setBoolean(config, false); } catch (Exception e) { // ignore } } @Override public void setContentView(int layoutResID) { addSwipeLayout(LayoutInflater.from(this).inflate(layoutResID, null)); } @Override public void setContentView(View view) { addSwipeLayout(view); } private View buildToolbarLayout(View view) { if (isToolbarEnable()) { mToolbarLayout = new ToolbarLayout.Builder(this) .setContentView(view) .setOverlay(isToolbarOverlay()) .setShadow(isToolbarHasShadow()) .build(); mToolbarLayout.setLeftIcon(R.drawable.back); mToolbarLayout.setOnClickListener(new ToolbarLayout.OnClickListener() { @Override public void onLeftClick(View view) { onToolbarLeftClick(view); } @Override public void onCenterClick(View view) { onToolbarTitleClick(view); } @Override public void onRightClick(View view) { onToolbarRightClick(view); } }); return mToolbarLayout; } return view; } private void addSwipeLayout(View view) { //1.将view转换为四层结构的baseLayout view = buildContentView(view); //2.将view转换成带标题栏的view view = buildToolbarLayout(view); //3.加上swipeBack buildSwipeLayout(); mSwipeBackLayout.setEnableGesture(isSwipeBackEnabled()); super.setContentView(view); } private SwipeBackLayout buildSwipeLayout() { mSwipeBackLayout = (SwipeBackLayout) LayoutInflater.from(this).inflate( R.layout.vw_swipeback_layout, null); mSwipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT); final Activity activity = this; mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { @Override public void onScrollStateChange(int state, float scrollPercent) { onSwipeScrollStateChange(state, scrollPercent); } @Override public void onEdgeTouch(int edgeFlag) { UIHelper.convertActivityToTranslucent(activity); onSwipeEdgeTouch(edgeFlag); } @Override public void onScrollOverThreshold() { } }); return mSwipeBackLayout; } protected void onSwipeScrollStateChange(int state, float scrollPercent) { } protected void onSwipeEdgeTouch(int edgeFlag) { } /** * 标题栏左侧图标/文字 点击时候的回调 * * @param view */ public void onToolbarLeftClick(View view) { finish(); } /** * 标题栏中间图标/文字 点击时候的回调 * * @param view */ public void onToolbarTitleClick(View view) { } /** * 标题栏右侧图标/文字 点击时候的回调 * * @param view */ public void onToolbarRightClick(View view) { showPopMenu(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) { if (null != mHandler) { //用handler post 是为了修复点击菜单键,popMenu闪现的问题,Bugzilla:30303 mHandler.postDelayed(this::showPopMenu, 140); } } else if (keyCode == KeyEvent.KEYCODE_BACK) { if (mBaseFragment == null || !mBaseFragment.onBackPressed()) { return super.onKeyDown(keyCode, event); } else { return true; } } return super.onKeyDown(keyCode, event); } private void showPopMenu() { if (mPopupMenu != null) { if (mIsPopupMenuShow) { mPopupMenu.dismiss(); } else { mPopupMenu.show(); } mIsPopupMenuShow = !mIsPopupMenuShow; } } private View buildContentView(View view) { if (hasBaseLayout()) { BaseLayout.Builder builder = getLayoutBuilder(); if (null != builder) { mBaseLayout = builder.setContentView(view) .setProgressBarViewBg(getProgressBg()) .build(); return mBaseLayout; } } return view; } @Override protected void onResume() { super.onResume(); if (!mIsInitialized) { mIsInitialized = true; onLazyLoad(); } // TalkData统计 TCAgent.onResume(this); } @Override protected void onPause() { super.onPause(); // TalkData统计 TCAgent.onPause(this); } @Override protected void onStop() { super.onStop(); } /** * 懒加载,需要请求网络的activity需要将网络请求放在此方法当中 */ protected void onLazyLoad() { } /** * 避免一些耗时的事件返回的回调在返回时出现NullPointException,需要把这些Subscription在生命周期结束时接触订阅关系,见onDestroy()中业务 * * @param subscription */ public void addSubscription(Subscription subscription) { if (subscription != null) { if (mCompositeSubscription == null || mCompositeSubscription.isUnsubscribed()) { mCompositeSubscription = new CompositeSubscription(); } mCompositeSubscription.add(subscription); } } @Override protected void onDestroy() { //回收资源 if (mCompositeSubscription != null) { mCompositeSubscription.unsubscribe(); } if (mViewModel != null) { mViewModel = null; } mDestroyed = true; RxBusManager.unregister(this); // 这里统一隐藏显示的对话框 dismissProgressDialog(); ZjbApplication.removeActivity(this); ViewLayoutUtil.fixInputMethodManagerLeak(this); super.onDestroy(); } @Override protected void onTitleChanged(CharSequence title, int color) { super.onTitleChanged(title, color); } @Override public boolean isDestroyed() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return mDestroyed || super.isDestroyed(); } else { return mDestroyed; } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: onBackPressed(); return true; default: return super.onOptionsItemSelected(item); } } @Override public boolean onMenuOpened(int featureId, Menu menu) { if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { if ("MenuBuilder".equals(menu.getClass().getSimpleName())) { try { Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); method.setAccessible(true); method.invoke(menu, true); } catch (Exception e) { // ignore } } } return super.onMenuOpened(featureId, menu); } @Override public void onClickRetry() { // 如果子类需要处理错误重试事件,则需覆盖此方法 } @Override public void onClickEmpty() { // 如果子类需要处理空页面点击事件,则需覆盖此方法 } @Override public void onCancel(DialogInterface dialog) { } /** * <p> 获取布局Builder,主要用于自定义每个页面的progress、empty、error等View. <br/> * 需要自定义的页面需自行覆盖实现. </p> * * @return */ protected BaseLayout.Builder getLayoutBuilder() { BaseLayout.Builder builder = new BaseLayout.Builder(this); builder.setOnBaseLayoutClickListener(this); return builder; } /** * 是否包含基本view如progress、empty、error等. * * @return */ protected boolean hasBaseLayout() { return false; } /** * Is Toolbar enable. * * @return */ protected boolean isToolbarEnable() { return true; } protected boolean isToolbarHasShadow() { return true; } /** * @return 颜色的resource id */ protected int getProgressBg() { return android.R.color.transparent; } /** * Is Toolbar overlay. * * @return */ protected boolean isToolbarOverlay() { return false; } /** * Has Toolbar navigation. * * @return */ protected boolean hasToolbarNavigation() { return true; } /** * 进度条取消事件回调,需要的子类自行实现 */ protected void onProgressCanceled() { } /** * Get status bar height. * * @return */ public final float getStatusBarHeight() { int height = getResources().getIdentifier("status_bar_height", "dimen", "android"); return getResources().getDimension(height); } /** * Hide navigation bar. */ public final void hideNavigationBar() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_IMMERSIVE; View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility(uiOptions); } else { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; getWindow().setAttributes(lp); } } /** * Make full screen in all Android version. */ public final void makeFullScreen() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Hide the status bar and navigation bar. int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility(uiOptions); } else { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; getWindow().setAttributes(lp); } } /** * If the Android version is higher than KitKat(API>=19) <br> use this call to show & hide * * @param enable */ @SuppressLint("NewApi") public final void makeFullScreenAfterKitKat(boolean enable) { try { View decorView = getWindow().getDecorView(); if (enable) { int uiOptionsEnable = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; decorView.setSystemUiVisibility(uiOptionsEnable); } else { int uiOptionsDisable = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; decorView.setSystemUiVisibility(uiOptionsDisable); } } catch (Exception e) { WindowManager.LayoutParams lp = getWindow().getAttributes(); if (enable) { lp.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; } else { lp.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } getWindow().setAttributes(lp); } } /** * Set translucent status bar enable. * * @param enable */ protected final void setTranslucentStatusEnable(boolean enable) { mTranslucentStatusEnable = enable; } /** * Set translucent navigation bar enable. * * @param enable */ protected final void setTranslucentNavigationEnable(boolean enable) { mTranslucentNavigationEnable = enable; } /** * 透明导航栏 API>=19才有效 */ private void translucentNavigationBar() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 透明导航栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } SystemBarUtil systemBarUtil = new SystemBarUtil(this); systemBarUtil.setNavigationBarTintEnabled(true); systemBarUtil.setNavigationBarTintResource(android.R.color.transparent); } /** * 透明状态栏 API>=19才有效 */ private void translucentStatusBar() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 透明状态栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // setTranslucentStatus(true); } SystemBarUtil systemBarUtil = new SystemBarUtil(this); systemBarUtil.setStatusBarTintEnabled(true); systemBarUtil.setStatusBarTintResource(R.color.toolbar_bg); } @TargetApi(19) private void setTranslucentStatus(boolean on) { Window win = getWindow(); WindowManager.LayoutParams winParams = win.getAttributes(); final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; if (on) { winParams.flags |= bits; } else { winParams.flags &= ~bits; } win.setAttributes(winParams); } protected boolean canShowDialog() { return !(isDestroyed() || isFinishing()); } /** * 显示progress */ public void showProgressDialog(int resId) { if (mProgressDialog != null && mProgressDialog.isShowing()) { return; } mProgressDialog = DialogHelper.create(DialogHelper.TYPE_PROGRESS) .cancelable(true) .canceledOnTouchOutside(false) .progressText(getResources().getString(resId)) .show(); } /** * Dismiss progress dialog. */ public void dismissProgressDialog() { if (isProgressDialogShowing()) { mProgressDialog.dismiss(); mProgressDialog = null; } } /** * Is progress dialog showing. * * @return */ public boolean isProgressDialogShowing() { return null != mProgressDialog && mProgressDialog.isShowing(); } /** * Show empty view when the data of current page is null. */ public void showEmptyView() { if (null != mBaseLayout) { mBaseLayout.showEmptyView(); } } /** * Show error view when the request of current page is failed. */ public void showErrorView() { if (null != mBaseLayout) { mBaseLayout.showErrorView(); } } /** * Show progress view when request data first come in the page. */ public void showProgressView() { if (null != mBaseLayout) { mBaseLayout.showProgressView(); } } /** * Show content view of current page. */ public void showContentView() { if (null != mBaseLayout) { mBaseLayout.showContentView(); } } public void inflateMenu(@MenuRes int menuRes) { mToolbarLayout.setRightIcon(R.drawable.toolbar_overflow); if (mPopupMenu == null) { mPopupMenu = new PopupMenu(this, mToolbarLayout.getTitlebar(), Gravity.TOP | Gravity.END); } if (mMenuRes != menuRes) { mMenuRes = menuRes; mPopupMenu.inflate(menuRes); mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { return onPopMenuItemClick(item); } }); mPopupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() { @Override public void onDismiss(PopupMenu menu) { mIsPopupMenuShow = false; } }); } } public void hidePopMenu() { if (mPopupMenu != null) { mPopupMenu.dismiss(); } } protected boolean onPopMenuItemClick(MenuItem item) { return false; } /** * 是否可以滑动退出界面 * * @return shi否可以滑动退出 */ public boolean isSwipeBackEnabled() { return true; } /** * 获取状态栏的颜色 */ public int getStatusBarColor() { return getResources().getColor(R.color.themes_main); } }