抓住人生中的一分一秒,胜过虚度中的一月一年!
前言
在Android开发中,activity再常用不过了,为了高效开发,我们会将一些常用的功能和页面统一实现的效果放在基类,这样就不用写每个页面时再重新实现这些功能,下面是我总结了些内容与大家共享一下,有不足的地方希望大家提出我将进行再次完善。
实现目标
1、屏幕横竖屏切换,AndroidManifest中将不用再写android:screenOrientation="portrait"
2、ButterKnife绑定页面
3、沉浸式实现
4、携带数据的页面跳转
5、应用被强杀检测
6、标题栏统一实现
7、仿IOS侧滑finish页面实现
8、Loading页面统一实现(可替换成骨架图)
9、点击Edittext弹出软键盘,点击空白区域让软键盘消失
10、结合MVP模式下的BaseActivity
1、屏幕横竖屏切换,AndroidManifest中将不用再写android:screenOrientation="portrait"
我们经常开发的app,一般情况下都是手机上的应用,我想大家已经设置了强制竖屏,因为横屏没有特殊要求没有必要去设置,设置了反而会出现更多问题,其次说一下8.0更新问题,页面同时设置了android:screenOrientation="portrait"和透明属性,8.0运行会出现Only fullscreen opaque activities can request orientation异常,大概意思为“只有不透明的全屏activity可以自主设置界面方向”,我们或许会引用一些第三方SDK到项目中,也许第三方会用到透明属性,我们可能在AndroidManifest中会申明android:screenOrientation="portrait"后导致莫名其妙的奔溃(小概率事件,但不排除),所以建议在BaseActivity设置比较优(当你做侧滑返回以后就不会觉得我说这么啰嗦了)
/** * 设置屏幕横竖屏切换 * * @param screenRoate true 竖屏 false 横屏 */ private void setScreenRoate(Boolean screenRoate) { if (screenRoate) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置竖屏模式 } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setScreenRoate(true); }
2、ButterKnife绑定页面
ButterKnife这个快速申明控件省了我们多少findViewById的时间,推荐使用,详细写一写可能有人没用过此控件
1、依赖
compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
2、onCreate绑定页面 onDestroy取消绑定
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ButterKnife.bind(this); } @Override protected void onDestroy() { super.onDestroy(); ButterKnife.bind(this).unbind(); }
3、沉浸式实现
为了让用户感受更好的体验效果,所以我们会选择设置沉浸式,每个页面大多数都会设置一种效果,所以直接在BaseActivity设置即可
/** * 沉浸式实现 */ protected void setStatusBar() { StatusBarUtil.setColor(this, getResources().getColor(R.color.colorWhite), 0); // StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStatusBar(); }
问:如果有页面不想设置此效果
答:在对应Activity重写setStatusBar(),做自定义操作
4、携带数据的页面跳转
跳转页面 startActivity(new Intent(this, MainActivity.class));不改装这已经是最简洁了,你要记住,程序员是比较懒的,能少写就少写
/** * [页面跳转] * * @param clz */ public void startActivity(Class<?> clz) { startActivity(clz, null); } /** * [携带数据的页面跳转] * * @param clz * @param bundle */ public void startActivity(Class<?> clz, Bundle bundle) { Intent intent = new Intent(); intent.setClass(this, clz); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); } /** * [含有Bundle通过Class打开编辑界面] * * @param cls * @param bundle * @param requestCode */ public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); }
跳转页面startActivity(MainActivity.class);嗯。。。少写了几个字母
5、应用被强杀检测
手机开了N多个应用,可能导致内存不足,所以GC就出来工作了,也许你的App就是被杀的对象(保活处理移步其他文章),我们需要检测到APP是否被杀
思路:
(1)APP被杀,可以跳转到闪屏页,再跳转到MainActivity,但可能MainActivity还存在,我想让MainActivity彻底消失,所以我的思路是跳转到MainActivity,将MainActivity finish再跳转到闪屏页,再往其他页面跳转
(2)那怎么样检测APP是否被杀呢,我进入到APP后将一个参数设置个值,如果APP被杀,也就是说我们当时设置的值已经不存在了,当我们检测到这个值和我们当时设置的值不匹配说明APP被杀了
1、新建个常量类AppStatusConstant
/** * File descripition: APP状态跟踪器常量码 * * @author lp * @date 2018/9/29 */ public class AppStatusConstant { public static final int STATUS_FORCE_KILLED=-1; //应用放在后台被强杀了 public static final int STATUS_NORMAL=2; //APP正常态 //intent到MainActivity 区分跳转目的 public static final String KEY_HOME_ACTION="key_home_action";//返回到主页面 public static final int ACTION_BACK_TO_HOME=6; //默认值 public static final int ACTION_RESTART_APP=9;//被强杀 }
2、新建个单例模式,用来保存值
/** * File descripition: * * @author lp * @date 2018/9/29 */ public class AppStatusManager { public int appStatus= AppStatusConstant.STATUS_FORCE_KILLED; //APP状态 初始值为没启动 不在前台状态 public static AppStatusManager appStatusManager; private AppStatusManager() { } public static AppStatusManager getInstance() { if (appStatusManager == null) { appStatusManager = new AppStatusManager(); } return appStatusManager; } public int getAppStatus() { return appStatus; } public void setAppStatus(int appStatus) { this.appStatus = appStatus; } }
3、进入到闪屏页我便给appStatus赋值
/** * File descripition: 闪屏页 * * @author lp * @date 2018/10/16 */ public class SplashActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AppStatusManager.getInstance().setAppStatus(AppStatusConstant.STATUS_NORMAL); //进入应用初始化设置成未登录状态 super.onCreate(savedInstanceState); } }
4、在BaseActivity的onCreate中去检测这个值是否是我们设置过的值
private void initAppStatus() { switch (AppStatusManager.getInstance().getAppStatus()) { /** * 应用被强杀 */ case AppStatusConstant.STATUS_FORCE_KILLED: //跳到主页,主页lauchmode SINGLETASK protectApp(); break; } } protected void protectApp() { Intent intent = new Intent(this, MainActivity.class); intent.putExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_RESTART_APP); startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initAppStatus(); }
5、MainActivity中接收传过来的信息,然后调整到闪屏页
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); int action = intent.getIntExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_BACK_TO_HOME); switch (action) { case AppStatusConstant.ACTION_RESTART_APP: protectApp(); break; } } @Override protected void protectApp() { Toast.makeText(getApplicationContext(), "应用被回收重新启动", Toast.LENGTH_LONG).show(); startActivity(new Intent(this, SplashActivity.class)); finish(); }
6、标题栏统一实现
每个页面大多数都会有个标题栏,实现方式我们都会,下面我介绍另一种方式,我把标题栏写到BaseActivity布局中,这样在对应的Activity就不用一遍一遍的写了,但是弊端是多了一层嵌套
思路:我们在BaseActivity申明一个布局,其子Activity的xml塞入到父布局的一个控件中,这样就每个子Activity都会有统一的控件了(标题栏)
1、首先新建个关于title的xml,app_title.xml(供参考)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rlt_base" android:layout_width="match_parent" android:layout_height="44dp" android:background="@color/colorWhite"> <LinearLayout android:id="@+id/back" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="@dimen/padding_12" android:paddingRight="@dimen/padding_12"> <TextView android:id="@+id/back_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="@dimen/margin_8" android:drawableLeft="@mipmap/zuojiantou" android:drawablePadding="@dimen/padding_8" android:gravity="center" android:textColor="@color/colorBlack" android:visibility="visible" /> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:layout_marginLeft="80dp" android:layout_marginRight="80dp"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:layout_centerInParent="true" android:ellipsize="end" android:gravity="center" android:lines="1" android:textColor="@color/colorBlack" android:textSize="@dimen/text_18" /> </RelativeLayout> <TextView android:id="@+id/tv_right" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:drawablePadding="@dimen/padding_6" android:ellipsize="end" android:gravity="center" android:lines="1" android:paddingLeft="14dp" android:paddingRight="14dp" android:textColor="@color/colorBlack" android:textSize="@dimen/text_16" android:visibility="visible" /> <View style="@style/View_o_5" android:layout_alignParentBottom="true" /> </RelativeLayout>
2、创建父布局的xml,activity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include layout="@layout/app_title" /> <FrameLayout android:id="@+id/fl_content" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
3、都创建好了就该给BaseActivity设置布局了
public abstract class BaseActivityNall extends AppCompatActivity { public TextView mBackName; public LinearLayout mBack; public TextView mTvTitle; public TextView mTvRight; public RelativeLayout mRltBase; protected View rootView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); rootView = View.inflate(this, R.layout.activity_title, null); setContentView(getLayoutId()); addContent(); setContentView(rootView); } private void addContent() { mBackName = (TextView) rootView.findViewById(R.id.back_name); mBack = (LinearLayout) rootView.findViewById(R.id.back); mTvTitle = (TextView) rootView.findViewById(R.id.tv_title); mTvRight = (TextView) rootView.findViewById(R.id.tv_right); mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base); FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content); mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle()); mBack.setOnClickListener(v -> finish());//java8写法,特此备注一下 View content = View.inflate(this, getLayoutId(), null); if (content != null) { FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); flContent.addView(content, params); ButterKnife.bind(this, rootView); } } /** * 获取布局ID * * @return */ protected abstract int getLayoutId(); /** * title赋值 * * @return */ protected abstract String getContentTitle(); }
7、仿IOS侧滑finish页面实现
实现侧滑会有很多弊端,在此就不细讲实现方式了,给大家演示一种,但是想完美实现还需进一步完善,第三方库实现,方法在BaseActivity写
implementation 'com.r0adkll:slidableactivity:2.0.6' /** * 初始化滑动返回 */ protected void initSlidable() { int isSlidable = SettingUtil.getInstance().getSlidable(); if (isSlidable != Constants.SLIDABLE_DISABLE) { SlidrConfig config = new SlidrConfig.Builder() .edge(isSlidable == Constants.SLIDABLE_EDGE) .build(); slidrInterface = Slidr.attach(this, config); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initSlidable(); } // Base application theme. <style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> // <item name="android:windowAnimationStyle">@style/activityAnimation</item> <item name="android:windowIsTranslucent">true</item> <!--<item name="android:windowDisablePreview">true</item>--> <item name="android:windowBackground">@android:color/transparent</item> </style>
有很多类似的开源框架 暂举四个
8、Loading页面统一实现(可替换成骨架图)
看了一个大神写的一个框架,超级来感觉呀 spruce-android,在BaseActivity封装简单的给大家演示下,具体封装大家去实现
/** * File descripition: activity基类 * <p> * * @author lp * @date 2018/5/16 */ public abstract class BaseActivityNall extends AppCompatActivity implements BaseView { public TextView mBackName; public LinearLayout mBack; public TextView mTvTitle; public TextView mTvRight; public RelativeLayout mRltBase; public int mIndex = BaseContent.baseIndex; protected View rootView; protected LoadService mBaseLoadService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); rootView = View.inflate(this, R.layout.activity_title, null); setContentView(getLayoutId()); addContent(); setContentView(rootView); this.initData(); this.getData(); } private void addContent() { mBackName = (TextView) rootView.findViewById(R.id.back_name); mBack = (LinearLayout) rootView.findViewById(R.id.back); mTvTitle = (TextView) rootView.findViewById(R.id.tv_title); mTvRight = (TextView) rootView.findViewById(R.id.tv_right); mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base); FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content); mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle()); mBack.setOnClickListener(v -> finish());//java8写法,特此备注一下 View content = View.inflate(this, getLayoutId(), null); if (content != null) { FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); flContent.addView(content, params); ButterKnife.bind(this, rootView); mBaseLoadService = LoadSir.getDefault().register(content, new Callback.OnReloadListener() { @Override public void onReload(View v) { onNetReload(v); } }); } } protected void onNetReload(View v) { mBaseLoadService.showCallback(LoadingCallback.class); mIndex = BaseContent.baseIndex; getData(); } /** * 获取布局ID * * @return */ protected abstract int getLayoutId(); /** * title赋值 * * @return */ protected abstract String getContentTitle(); /** * 数据初始化操作 */ protected abstract void initData(); /** * 请求数据 */ protected abstract void getData(); }
9、点击Edittext弹出软键盘,点击空白区域让软键盘消失
在我们使用Edittext时,软键盘弹出了,写完字之后,想让它消失,不去处理想让软键盘消失需要点击软键盘中的消失按钮,显然不是很方便的方法,我们想点击非Edittext任何地方都让软键盘(也可以点击Edittext让软键盘消失),请往下看,有俩种实现方法
(1)、第一种实现方法,扩展性差
@Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if (isShouldHideKeyboard(v, ev)) { hideKeyboard(v.getWindowToken()); } } return super.dispatchTouchEvent(ev); } /** * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏 * * @param v * @param event * @return */ private boolean isShouldHideKeyboard(View v, MotionEvent event) { if (v != null && (v instanceof EditText)) { int[] l = {0, 0}; v.getLocationInWindow(l); int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth(); if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) { // 点击EditText的事件,忽略它。 return false; } else { return true; } } // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点 return false; } /** * 获取InputMethodManager,隐藏软键盘 * * @param token */ private void hideKeyboard(IBinder token) { if (token != null) { InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); } }
(2)、第二种实现方法(推荐使用)
/** * 以下是关于软键盘的处理 */ /** * 清除editText的焦点 * * @param v 焦点所在View * @param ids 输入框 */ public void clearViewFocus(View v, int... ids) { if (null != v && null != ids && ids.length > 0) { for (int id : ids) { if (v.getId() == id) { v.clearFocus(); break; } } } } /** * 隐藏键盘 * * @param v 焦点所在View * @param ids 输入框 * @return true代表焦点在edit上 */ public boolean isFocusEditText(View v, int... ids) { if (v instanceof EditText) { EditText et = (EditText) v; for (int id : ids) { if (et.getId() == id) { return true; } } } return false; } //是否触摸在指定view上面,对某个控件过滤 public boolean isTouchView(View[] views, MotionEvent ev) { if (views == null || views.length == 0) { return false; } int[] location = new int[2]; for (View view : views) { view.getLocationOnScreen(location); int x = location[0]; int y = location[1]; if (ev.getX() > x && ev.getX() < (x + view.getWidth()) && ev.getY() > y && ev.getY() < (y + view.getHeight())) { return true; } } return false; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if (isTouchView(filterViewByIds(), ev)) { return super.dispatchTouchEvent(ev); } if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) { return super.dispatchTouchEvent(ev); } View v = getCurrentFocus(); if (isFocusEditText(v, hideSoftByEditViewIds())) { KeyBoardUtils.hideInputForce(this); clearViewFocus(v, hideSoftByEditViewIds()); } } return super.dispatchTouchEvent(ev); } /** * 传入EditText的Id * 没有传入的EditText不做处理 * * @return id 数组 */ public int[] hideSoftByEditViewIds() { return null; } /** * 传入要过滤的View * 过滤之后点击将不会有隐藏软键盘的操作 * * @return id 数组 */ public View[] filterViewByIds() { return null; }
使用方法:在对应的Activity重写hideSoftByEditViewIds()和filterViewByIds(),传入需要弹出的软键盘的ID
/*实现案例===============================================================================================*/ @Override public int[] hideSoftByEditViewIds() { int[] ids = {R.id.et_company_name, R.id.et_address}; return ids; } @Override public View[] filterViewByIds() { View[] views = {mEtCompanyName, mEtAddress}; return views; }
10、结合MVP模式下的BaseActivity,传送地址
/** * File descripition: activity基类 * <p> * * @author lp * @date 2018/5/16 */ public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView { protected final String TAG = this.getClass().getSimpleName(); public View mViewStatusBar; public TextView mBackName; public LinearLayout mBack; public TextView mTvTitle; public TextView mTvRight; public RelativeLayout mRltBase; public Activity mContext; protected P mPresenter; private LoadingDialog mLodingDialog; protected abstract P createPresenter(); //错误提示框 警告框 成功提示框 private PromptDialog promptDialog; public int mIndex = BaseContent.baseIndex; protected View rootView; protected LoadService mBaseLoadService; /** * 是否显示初始Loading */ private Boolean isShow = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置竖屏模式 mContext = this; rootView = View.inflate(this, R.layout.activity_title, null); setContentView(getLayoutId()); addContent(); setContentView(rootView); mPresenter = createPresenter(); AppManager.getAppManager().addActivity(this); setStatusBar(); initAppStatus(); ButterKnife.bind(this); this.initData(); } private void initAppStatus() { switch (AppStatusManager.getInstance().getAppStatus()) { /** * 应用被强杀 */ case AppStatusConstant.STATUS_FORCE_KILLED: //跳到主页,主页lauchmode SINGLETASK protectApp(); break; } } private void addContent() { mViewStatusBar = (View) rootView.findViewById(R.id.view_status_bar); mBackName = (TextView) rootView.findViewById(R.id.back_name); mBack = (LinearLayout) rootView.findViewById(R.id.back); mTvTitle = (TextView) rootView.findViewById(R.id.tv_title); mTvRight = (TextView) rootView.findViewById(R.id.tv_right); mRltBase = (RelativeLayout) rootView.findViewById(R.id.rlt_base); FrameLayout flContent = (FrameLayout) rootView.findViewById(R.id.fl_content); mTvTitle.setText(getContentTitle() == null ? "" : getContentTitle()); mBack.setOnClickListener(v -> finish()); View content = View.inflate(this, getLayoutId(), null); if (content != null) { FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); flContent.addView(content, params); ButterKnife.bind(this, rootView); mBaseLoadService = LoadSir.getDefault().register(content, new Callback.OnReloadListener() { @Override public void onReload(View v) { showLoadingLayout(); mIndex = BaseContent.baseIndex; getData(); } }); if (isShow) { showLoadingLayout(); } else { PostUtil.postSuccessDelayed(mBaseLoadService, 0); } } } protected void protectApp() { Intent intent = new Intent(this, MainActivity.class); intent.putExtra(AppStatusConstant.KEY_HOME_ACTION, AppStatusConstant.ACTION_RESTART_APP); startActivity(intent); } private void showLoadingLayout() { mBaseLoadService.showCallback(LoadingCallback.class); } public void showLoadingLayout(boolean isShow) { this.isShow = isShow; } /** * 获取布局ID * * @return */ protected abstract int getLayoutId(); /** * title赋值 * * @return */ protected abstract String getContentTitle(); /** * 数据初始化操作 */ protected abstract void initData(); /** * 请求数据 */ protected abstract void getData(); /** * 沉浸式实现 */ protected void setStatusBar() { StatusBarUtil.setColor(this, getResources().getColor(R.color.colorWhite), 0); // StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null); } public void showToast(String str) { showToast(str, Toast.LENGTH_SHORT); } public void showLongToast(String str) { showToast(str, Toast.LENGTH_LONG); } /** * 封装toast方法 * * @param str * @param dur */ void showToast(String str, int dur) { ToastUtils.showToastS(this, str, dur); } @Override public void showError(String msg) { showToast(msg); } @Override public void onErrorCode(BaseModel model) { if (model.getErrcode() == BaseObserver.NETWORK_ERROR) {//网络连接失败 无网 PostUtil.postCallbackDelayed(mBaseLoadService, NetWorkErrorCallback.class); } else if (model.getErrcode() == BaseObserver.CONNECT_ERROR ||//连接错误 model.getErrcode() == BaseObserver.CONNECT_TIMEOUT ||//连接超时 model.getErrcode() == BaseObserver.BAD_NETWORK ||//网络超时 model.getErrcode() == BaseObserver.CONNECT_NULL//数据为空,显示异常 ) { PostUtil.postCallbackDelayed(mBaseLoadService, ErrorCallback.class); } else if (model.getErrcode() == BaseObserver.CONNECT_NOT_LOGIN) {//没有登录,去登录 startLogin(); } } private void startLogin() { AppUMS.mIsLogin = false; AppUMS.setToken(""); startActivity(LoginActivity.class); } @Override public void showLoading() { showLoadingDialog(); } @Override public void hideLoading() { closeLoadingDialog(); } public void closeLoadingDialog() { if (mLodingDialog != null && mLodingDialog.isShowing()) { mLodingDialog.dismiss(); } } /** * 加载... */ public void showLoadingDialog() { if (mLodingDialog == null) { mLodingDialog = new LoadingDialog(this).setMessage(getString(R.string.app_loding)); } mLodingDialog.show(); } /** * 警告框 */ public void showInfoDialog(String msg) { if (promptDialog == null) { promptDialog = new PromptDialog(this); } promptDialog.showInfo(msg); } /** * 错误提示框 */ public void showErrorDialog(String msg) { if (promptDialog == null) { promptDialog = new PromptDialog(this); } promptDialog.showError(msg); } /** * 成功提示框 */ public void showSuccessDialog(String msg) { if (promptDialog == null) { promptDialog = new PromptDialog(this); } promptDialog.showSuccess(msg); } @Override protected void onResume() { super.onResume(); MobclickAgent.onResume(this); } @Override protected void onPause() { super.onPause(); MobclickAgent.onPause(this); } @Override protected void onDestroy() { super.onDestroy(); ButterKnife.bind(this).unbind(); AppManager.getAppManager().finishActivity(this); if (mPresenter != null) { mPresenter.detachView(); } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { finishActivity(); return false; } return super.dispatchKeyEvent(event); } public void finishActivity() { finish(); } /** * [页面跳转] * * @param clz */ public void startActivity(Class<?> clz) { startActivity(clz, null); } /** * [携带数据的页面跳转] * * @param clz * @param bundle */ public void startActivity(Class<?> clz, Bundle bundle) { Intent intent = new Intent(); intent.setClass(this, clz); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); } /** * [含有Bundle通过Class打开编辑界面] * * @param cls * @param bundle * @param requestCode */ public void startActivityForResult(Class<?> cls, Bundle bundle, int requestCode) { Intent intent = new Intent(); intent.setClass(this, cls); if (bundle != null) { intent.putExtras(bundle); } startActivityForResult(intent, requestCode); } /** * 以下是关于软键盘的处理 */ /** * 清除editText的焦点 * * @param v 焦点所在View * @param ids 输入框 */ public void clearViewFocus(View v, int... ids) { if (null != v && null != ids && ids.length > 0) { for (int id : ids) { if (v.getId() == id) { v.clearFocus(); break; } } } } /** * 隐藏键盘 * * @param v 焦点所在View * @param ids 输入框 * @return true代表焦点在edit上 */ public boolean isFocusEditText(View v, int... ids) { if (v instanceof EditText) { EditText et = (EditText) v; for (int id : ids) { if (et.getId() == id) { return true; } } } return false; } //是否触摸在指定view上面,对某个控件过滤 public boolean isTouchView(View[] views, MotionEvent ev) { if (views == null || views.length == 0) { return false; } int[] location = new int[2]; for (View view : views) { view.getLocationOnScreen(location); int x = location[0]; int y = location[1]; if (ev.getX() > x && ev.getX() < (x + view.getWidth()) && ev.getY() > y && ev.getY() < (y + view.getHeight())) { return true; } } return false; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if (isTouchView(filterViewByIds(), ev)) { return super.dispatchTouchEvent(ev); } if (hideSoftByEditViewIds() == null || hideSoftByEditViewIds().length == 0) { return super.dispatchTouchEvent(ev); } View v = getCurrentFocus(); if (isFocusEditText(v, hideSoftByEditViewIds())) { KeyBoardUtils.hideInputForce(this); clearViewFocus(v, hideSoftByEditViewIds()); } } return super.dispatchTouchEvent(ev); } /** * 传入EditText的Id * 没有传入的EditText不做处理 * * @return id 数组 */ public int[] hideSoftByEditViewIds() { return null; } /** * 传入要过滤的View * 过滤之后点击将不会有隐藏软键盘的操作 * * @return id 数组 */ public View[] filterViewByIds() { return null; } /*实现案例===============================================================================================*/ /* @Override public int[] hideSoftByEditViewIds() { int[] ids = {R.id.et_company_name, R.id.et_address}; return ids; } @Override public View[] filterViewByIds() { View[] views = {mEtCompanyName, mEtAddress}; return views; } */ }
最后,祝大家开发顺利!