【Android实战】----从Activity入手(编写BaseActivity)
2017-02-07 15:55
274 查看
关于Android实战篇系列,一直不知从何入手写。基本概念介绍对于实战篇系列来讲没有太大意义,本系列一如Spring实战篇系列所倡导的理念一样:知其然知其所以然,难点、疑点一网打尽(有点狂妄了)。还是决定从头开始,这里对基本概念不做过多介绍,主要介绍使用。
一、背景知识
说到Activity,做Android的一点都不会陌生,真正项目开发中不止会用到Activity,而且会抽象出BaseActivity,其中处理公共部分(比如标题、回调函数等),具体部分还是有具体的Activity处理,这里也是利用了java中的设计模式——策略模式
二、BaseActivity配置
其中BaseActivity继承了Activity(这个是必须滴,凡是Activity都要集成SDK中的Activity),实现了TextWatcher(监听Editable变化,后面会介绍),实现了RetrofitCallBack(retrofit的回调接口,这个在后面说道retrofit的时候会说明);除此之外,还设置了共用的title,返回键,openActivity,goLogin,等待对话框等。
三、BaseActivity的使用
下面以登录界面为例,介绍BaseActivity的使用
1)先看界面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_light" >
<include
android:id="@+id/title"
android:layout_alignParentTop="true"
layout="@layout/layout_stub_title" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/distanse60">
<EditText
android:id="@+id/et_account"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse50"
android:background="@drawable/reg_input_bg2"
android:drawableLeft="@drawable/phone"
android:drawablePadding="@dimen/distanse10"
android:hint="请输入手机/用户名"
android:paddingLeft="@dimen/distanse15"
android:paddingRight="@dimen/distanse10"
android:textColor="@color/lightblack" />
<View android:layout_width="match_parent" android:layout_height="1dp"
android:background="#ccc" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse50"
android:background="@drawable/reg_input_bg2"
android:drawableLeft="@drawable/password"
android:drawablePadding="@dimen/distanse10"
android:hint="登录密码"
android:inputType="textPassword"
android:paddingLeft="@dimen/distanse15"
android:paddingRight="@dimen/distanse10"
android:textColor="@color/lightblack" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/distanse10"
android:layout_marginRight="@dimen/distanse10"
android:layout_marginTop="@dimen/distanse50"
android:padding="@dimen/distanse10"
android:background="@drawable/buttonstyle"
android:enabled="false"
android:gravity="center"
android:text="确定"
android:textColor="@color/white"
android:textSize="@dimen/text_size16" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_reset"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse40"
android:layout_marginLeft="@dimen/distanse15"
android:layout_marginRight="@dimen/distanse15"
android:layout_marginTop="@dimen/distanse10"
android:drawablePadding="@dimen/distanse5"
android:gravity="right"
android:text="忘记密码"
android:textColor="@color/light_blue"
android:textSize="@dimen/text_size15"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="@dimen/distanse10">
<TextView
android:id="@+id/tv_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="@dimen/distanse10"
android:text="还没有账号?现在注册"
android:textColor="@color/light_blue"
android:textSize="@dimen/text_size14"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
其中引入了共用title布局
2)LoginActivity
后面retrofit相关是和服务器通信的,这个后面会有专题介绍。还看到控件的获取和点击事件的设置用了Butterknife,@BindView和@OnClick,这个将在下一章进行介绍Butterknife的使用
四、AndroidManifest.xml
当然不要忘了在AndroidManifest.xml进行设置,否则无法启动
运行效果图
一、背景知识
说到Activity,做Android的一点都不会陌生,真正项目开发中不止会用到Activity,而且会抽象出BaseActivity,其中处理公共部分(比如标题、回调函数等),具体部分还是有具体的Activity处理,这里也是利用了java中的设计模式——策略模式
二、BaseActivity配置
/** * 基本Activity,供其他Activity继承,实现了回调及title设置、返回按键等 */ public class BaseActivity extends Activity implements TextWatcher,RetrofitCallBack { protected ProgressDialog waitDialog; /** * 标记标题左右两边的类型:文字 */ protected final int TITLE_TYPE_TEXT = 0; /** * 标记标题左右两边的类型:图片 */ protected final int TITLE_TYPE_IMG = 1; public MyApplication application; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); application = (MyApplication) getApplicationContext(); } @Override protected void onDestroy() { super.onDestroy(); dismissWaitDialog(); } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); // 判断界面再次转到前台的时候,主题是否发生改变.如果改变了,则需要重新加载activity // this.recreate(); } @Override protected void onStop() { super.onStop(); } /** * 需在setContentView方法之后调用. 设置后,如果不对左侧的事件进行监听,默认的点击事件是结束当前界面. * <p> * 标题传资源id和字符串皆可. * <p> * 如果某一侧显示的是图片,则那一侧只能传对应的图片资源id.如果是文字,则资源id和字符串皆可. * * @param title * 标题 * @param left * 是否显示左侧的部分 * @param leftType * 左侧的类型 * @param l * 左侧部分内容 * @param right * 是否显示右侧的部分 * @param rightType * 右侧的类型 * @param r * 右侧部分的内容 */ protected void setTitle(Object title, boolean left, int leftType, Object l, boolean right, int rightType, Object r) { try { TextView tvTitle = (TextView) findViewById(R.id.tv_title); TextView tvLeft = (TextView) findViewById(R.id.tv_title_left); LinearLayout llLeft = (LinearLayout) findViewById(R.id.ll_title_left); ImageView ivLeft = (ImageView) findViewById(R.id.iv_title_left); TextView tvRight = (TextView) findViewById(R.id.tv_title_right); ImageView ivRight = (ImageView) findViewById(R.id.iv_title_right); LinearLayout llRight = (LinearLayout) findViewById(R.id.ll_title_right); if (title != null && title instanceof String) { if (!TextUtils.isEmpty((String) title)) { tvTitle.setVisibility(View.VISIBLE); tvTitle.setText((String) title); } else { tvTitle.setVisibility(View.INVISIBLE); } } else if (title != null && title instanceof Integer) { if (((Integer) title) > 0) { tvTitle.setVisibility(View.VISIBLE); tvTitle.setText((Integer) title); } else { tvTitle.setVisibility(View.INVISIBLE); } } if (left) { llLeft.setVisibility(View.VISIBLE); if (leftType == TITLE_TYPE_TEXT) { ivLeft.setVisibility(View.GONE); tvLeft.setVisibility(View.VISIBLE); if (l instanceof String) { tvLeft.setText((String) l); } else if (l instanceof Integer) { tvLeft.setText((Integer) l); } } else if (leftType == TITLE_TYPE_IMG) { ivLeft.setVisibility(View.VISIBLE); tvLeft.setVisibility(View.GONE); if (l instanceof Integer) { ivLeft.setImageResource((Integer) l); } } } else { llLeft.setVisibility(View.INVISIBLE); } if (right) { llRight.setVisibility(View.VISIBLE); if (rightType == TITLE_TYPE_TEXT) { ivRight.setVisibility(View.GONE); tvRight.setVisibility(View.VISIBLE); if (r instanceof String) { tvRight.setText((String) r); } else if (r instanceof Integer) { tvRight.setText((Integer) r); } } else if (rightType == TITLE_TYPE_IMG) { ivRight.setVisibility(View.VISIBLE); tvRight.setVisibility(View.GONE); if (r instanceof Integer) { ivRight.setImageResource((Integer) r); } } } else { llRight.setVisibility(View.INVISIBLE); } } catch (Exception e) { } } /** * 设置点击左上角的返回事件.默认是finish界面 */ protected void registerBack() { LinearLayout llLeft = (LinearLayout) findViewById(R.id.ll_title_left); llLeft.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { BaseActivity.this.finish(); } }); } /** * 设置点击右上角的返回事件. */ protected void rightDo() { LinearLayout llRight = (LinearLayout) findViewById(R.id.ll_title_right); llRight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { rightDoWhat(); } }); } protected void rightDoWhat() { } // 封装跳转 public void openActivity(Class<?> c) { openActivity(c, null); } // 跳转 传递数据 bundel public void openActivity(Class<?> c, Bundle b) { openActivity(c, b, null); } public void openActivity(Class<?> c, Bundle b, Uri uri) { Intent intent = new Intent(this, c); if (b != null) { intent.putExtras(b); } if (uri != null) { intent.setData(uri); } startActivity(intent); } /** * 跳转登录界面 */ protected void goLogin() { Intent intent = new Intent(this, LoginActivity.class); intent.putExtra(Constant.NEEDLOGIN, true); startActivityForResult(intent, 33); } /** * 全局等待对话框 */ public void showWaitDialog() { this.runOnUiThread(new Runnable() { @Override public void run() { if (waitDialog == null || !waitDialog.isShowing()) { waitDialog = new ProgressDialog(BaseActivity.this); waitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); waitDialog.setCanceledOnTouchOutside(false); ImageView view = new ImageView(BaseActivity.this); view.setLayoutParams(new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); Animation loadAnimation = AnimationUtils.loadAnimation( BaseActivity.this, R.anim.rotate); view.startAnimation(loadAnimation); loadAnimation.start(); view.setImageResource(R.drawable.loading); // waitDialog.setCancelable(false); waitDialog.show(); waitDialog.setContentView(view); LogUtil.i("waitDialong......."); } } }); } public void dismissWaitDialog() { this.runOnUiThread(new Runnable() { @Override public void run() { if (waitDialog != null && waitDialog.isShowing()) { waitDialog.dismiss(); waitDialog = null; } } }); } /** * textWatcher的实现类,用于监听Editable的变化 * @param s * @param start * @param count * @param after */ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } /** * retrofitcallback方法实现,将response返回给Activity * @param response 返回数据 * @param method 回调方法标志 */ @Override public void onResponse(Response response, int method) { dismissWaitDialog(); } @Override public void onFailure(Response response, int method) { dismissWaitDialog(); } public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } }
其中BaseActivity继承了Activity(这个是必须滴,凡是Activity都要集成SDK中的Activity),实现了TextWatcher(监听Editable变化,后面会介绍),实现了RetrofitCallBack(retrofit的回调接口,这个在后面说道retrofit的时候会说明);除此之外,还设置了共用的title,返回键,openActivity,goLogin,等待对话框等。
三、BaseActivity的使用
下面以登录界面为例,介绍BaseActivity的使用
1)先看界面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_light" >
<include
android:id="@+id/title"
android:layout_alignParentTop="true"
layout="@layout/layout_stub_title" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/distanse60">
<EditText
android:id="@+id/et_account"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse50"
android:background="@drawable/reg_input_bg2"
android:drawableLeft="@drawable/phone"
android:drawablePadding="@dimen/distanse10"
android:hint="请输入手机/用户名"
android:paddingLeft="@dimen/distanse15"
android:paddingRight="@dimen/distanse10"
android:textColor="@color/lightblack" />
<View android:layout_width="match_parent" android:layout_height="1dp"
android:background="#ccc" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse50"
android:background="@drawable/reg_input_bg2"
android:drawableLeft="@drawable/password"
android:drawablePadding="@dimen/distanse10"
android:hint="登录密码"
android:inputType="textPassword"
android:paddingLeft="@dimen/distanse15"
android:paddingRight="@dimen/distanse10"
android:textColor="@color/lightblack" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/distanse10"
android:layout_marginRight="@dimen/distanse10"
android:layout_marginTop="@dimen/distanse50"
android:padding="@dimen/distanse10"
android:background="@drawable/buttonstyle"
android:enabled="false"
android:gravity="center"
android:text="确定"
android:textColor="@color/white"
android:textSize="@dimen/text_size16" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_reset"
android:layout_width="match_parent"
android:layout_height="@dimen/distanse40"
android:layout_marginLeft="@dimen/distanse15"
android:layout_marginRight="@dimen/distanse15"
android:layout_marginTop="@dimen/distanse10"
android:drawablePadding="@dimen/distanse5"
android:gravity="right"
android:text="忘记密码"
android:textColor="@color/light_blue"
android:textSize="@dimen/text_size15"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="@dimen/distanse10">
<TextView
android:id="@+id/tv_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="@dimen/distanse10"
android:text="还没有账号?现在注册"
android:textColor="@color/light_blue"
android:textSize="@dimen/text_size14"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
其中引入了共用title布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_title" android:layout_width="match_parent" android:layout_height="44dp" android:background="@color/blue1" android:gravity="center_vertical" > <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_toLeftOf="@+id/ll_title_right" android:layout_toRightOf="@+id/ll_title_left" android:ellipsize="end" android:gravity="center" android:text="New Text" android:textColor="@color/white" android:textSize="20sp" /> <LinearLayout android:id="@+id/ll_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:gravity="center_vertical|left" android:minWidth="80dp" android:orientation="horizontal" > <ImageView android:id="@+id/iv_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:paddingLeft="10dp" android:paddingRight="10dp" android:src="@drawable/to_left" /> <TextView android:id="@+id/tv_title_left" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center_vertical|left" android:paddingLeft="10dp" android:paddingRight="10dp" android:text="New Text" android:textColor="@color/white" android:textSize="16sp" android:visibility="gone" /> </LinearLayout> <LinearLayout android:id="@+id/ll_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:gravity="center_vertical|right" android:minWidth="80dp" android:orientation="horizontal" > <ImageView android:id="@+id/iv_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:paddingLeft="10dp" android:paddingRight="10dp" android:src="@drawable/to_left" /> <TextView android:id="@+id/tv_title_right" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center_vertical|right" android:paddingRight="10dp" android:text="New Text" android:textColor="@color/white" android:textSize="16sp" android:visibility="gone" /> </LinearLayout> </RelativeLayout>
2)LoginActivity
public class LoginActivity extends BaseActivity { @BindView(R.id.et_account) EditText etAccount; @BindView(R.id.et_pwd) EditText etPwd; @BindView(R.id.tv_reg) TextView tvReg; @BindView(R.id.tv_sure) TextView tvSure; private String account, pwd, userId, password; private boolean needLogin; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_login); //set布局 ButterKnife.bind(this); setTitle(R.string.login, true, TITLE_TYPE_IMG, R.drawable.to_left, true, TITLE_TYPE_TEXT, ""); //基类方法,设置title initView(); initData(); } private void initView() { registerBack(); //设置text变化监听器 etAccount.addTextChangedListener(this); etPwd.addTextChangedListener(this); tvReg.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);// 下划线 } /** * 根据是否输入值,判断是否显示确定按钮 * @param s */ @Override public void afterTextChanged(Editable s) { super.afterTextChanged(s); String userStr = etAccount.getText().toString(); String pwdStr = etPwd.getText().toString(); if(userStr.length() * pwdStr.length() != 0){ tvSure.setEnabled(true); }else{ tvSure.setEnabled(false); } } private void initData() { account = application.getUserinfobean().getPhoneNumber(); if (!StringUtil.isEmpty(account)) { etAccount.setText(account); } Intent intent = getIntent(); if (intent.hasExtra(Constant.NEEDLOGIN)) { needLogin = intent.getBooleanExtra(Constant.NEEDLOGIN, false); } } @OnClick({R.id.tv_sure, R.id.tv_reset, R.id.tv_reg}) public void onClick(View view) { account = etAccount.getText() + ""; switch (view.getId()) { case R.id.tv_sure: pwd = etPwd.getText() + ""; if (StringUtil.isEmpty(account)) { ToastUtil.makeShortText(this, "请输入登录账号"); return; } if (StringUtil.isEmpty(pwd)) { ToastUtil.makeShortText(this, "请输入登录密码"); return; } if (pwd.length() < 6 || pwd.length() > 16) { ToastUtil.makeShortText(this, "密码不能小于6位或大于16位"); return; } getUserById(account); break; case R.id.tv_reg: openActivity(RegisterActivity.class); break; case R.id.tv_reset: openActivity(ResetPwdActivity.class); break; default: break; } } private void getLogin(String userId, String password, String loginType) { showWaitDialog(); Map<String, Object> signMap = new HashMap<String, Object>(); signMap.put("name", userId); signMap.put("pwd", password); signMap.put("loginType", loginType); Map<String, String> reqMap = SignUtil.jsonMd5(signMap); RetrofitHttpRequest.addToEnqueue(RetrofitHttpRequest.getInstance().mHttpService.login(reqMap), this, HttpStaticApi.HTTP_LOGIN); } /** * 根据用户名获取userId,加密用md5(userId+pwd) */ private void getUserById(String name) { showWaitDialog(); Map<String, Object> signMap = new HashMap<String, Object>(); signMap.put("name", name); Map<String, String> reqMap = SignUtil.jsonMd5(signMap); RetrofitHttpRequest.addToEnqueue(RetrofitHttpRequest.getInstance().mHttpService.getUserById(reqMap), this, HttpStaticApi.HTTP_GETUSERBYID); } @Override public void onResponse(Response response, int method) { super.onResponse(response, method); switch (method) { case HttpStaticApi.HTTP_GETUSERBYID: UserIdBean userIdBean = (UserIdBean) response.body(); UserIdBean.ResDataBean resDataBean = userIdBean.getResData(); if (HttpConst.STATUS_SUC.equals(resDataBean.getStatus())) { userId = resDataBean.getData(); password = StringUtil.md5(userId + pwd); LogUtil.e(password); getLogin(account, password, "1"); } else { ToastUtil.makeShortText(this, resDataBean.getMessage()); } break; case HttpStaticApi.HTTP_LOGIN: UserBean userBean = (UserBean) response.body(); UserBean.ResDataBean resDataBean1 = userBean.getResData(); if (HttpConst.STATUS_SUC.equals(resDataBean1.getStatus())) { UserBean.ResDataBean.DataBean dataBean = resDataBean1.getData(); Bundle bundle = new Bundle(); bundle.putString("user_id", userId); bundle.putString("user_name", dataBean.getCustomerName()); bundle.putString("phone", dataBean.getMobile()); bundle.putString("nickName", dataBean.getNickName()); bundle.putString("email", dataBean.getEmail()); bundle.putBoolean("isBinding", dataBean.getIsbinding().equals("1") ? true : false); application.getUserinfobean().setAccess(bundle); //从需要登录页跳转的返回目标页,直接点击登录的跳转首页 if (!needLogin){ openActivity(MainActivity.class); } finish(); } else { ToastUtil.makeShortText(this, "登录失败" + resDataBean1.getMessage()); } break; default: break; } }
后面retrofit相关是和服务器通信的,这个后面会有专题介绍。还看到控件的获取和点击事件的设置用了Butterknife,@BindView和@OnClick,这个将在下一章进行介绍Butterknife的使用
四、AndroidManifest.xml
当然不要忘了在AndroidManifest.xml进行设置,否则无法启动
<activity android:name="com.xxx.xxx.login.LoginActivity" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan|stateHidden" />
运行效果图
相关文章推荐
- QtAndroid详解(3):startActivity实战Android拍照功能
- Activity实现退出和进入动画和BaseActivity的编写
- Android实战技术:启动另一个App/apk中的Activity
- Android实战技巧之二十六:persistableMode与Activity的持久化
- 在Android 2.3中如何使用native_activity.h编写本地应用
- 在Android 2.3中如何使用native_activity.h编写本地应用
- Android实战总结之返回键返回上一级Activity(Intent的一种用法)
- android小游戏制作心得(一)——Activity的编写
- android开发实战系列(10)-- 停止和重启Activity
- 【Android实战】----调用startActivityForResult()后,onActivityResult()立即执行的问题
- Android App框架设计之编写基类BaseActivity
- Android的Activity组件实战细节解析
- Android实战之Toolbar返回上级Activity崩溃的解决办法
- Android实战之Scrollbar Activity
- Android的Activity屏幕切换动画(二)-左右滑动深入与实战
- android开发实战系列(09)-- 暂停和恢复Activity
- Android的Activity屏幕切换动画-左右滑动深入与实战
- Android实战之Scrollbar Activity
- Android实战简易教程<五十二>(Fragment和Activity之间通信)