自己的新app项目,做了一个BaseActivity,参考了不少的资料,根据自己的需要改了不少.感觉为了偷懒已经到极限了
package com.corncq.mybaseframe;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import com.corncq.activity.ComplaintActivity;
import com.corncq.dxcx_user.R;
import com.corncq.my_enum.LayoutSelect;
import com.corncq.my_enum.PopWindowEnum;
import com.corncq.util.MyTextWatcher;
import com.corncq.util.SelectPicPopupWindow;
import com.corncq.util.SysApplication;
import com.corncq.util.UIHandler;
import com.corncq.view.CustomScrollView;
import com.corncq.view.XListView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by xiione on 2016/9/20.
* activity基类
*/
public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener {
private CustomScrollView customScrollView;
private ScrollView scrollView;
private LinearLayout linearLayout;
protected MyDialog progress; //加载进度圈
private Intent intent;
protected DisplayMetrics dm; //屏幕测量工具
protected MyTextWatcher watcher; //监测输入(如输入框,文本框等),后面贴代码
public boolean isWatcher = false; //是否开启控件监听,需要自己设置
public boolean isOtherWatcher = false; //是否开启控件监听,需要自己设置
public SelectPicPopupWindow basePopWindow; //弹出的pop
public BaseActivity() {
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//添加到回收站,方便一次性关闭所有打开过的页面
SysApplication.getInstance().addActivity(this);
dm = getResources().getDisplayMetrics();
setContentView(R.layout.activity_main);
progress = MyDialog.getInstance(this);
Bundle bundle = getIntent().getExtras();
initParms(bundle);
customScrollView = (CustomScrollView) findViewById(R.id.customScrollView);
scrollView = (ScrollView) findViewById(R.id.scrollView);
linearLayout = (LinearLayout) findViewById(R.id.linearLayout);
if (getScreen_exchange()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
//添加视图
View mView = bindView();
//判断视图是否为空
if (null == mView) {
//判断布局是否为空
if (bindLayout() != 0) {
//如果不为空,根据布局id,获取视图
mView = LayoutInflater.from(this).inflate(bindLayout(), null, false);
}
}
//获取到视图
if (null != mView) {
//选择 页面类型,是否可以滑动)
switch (selectView()) {
case CUSTOMSCROLLVIEW: //自定义scrollview,内部listview可滑动
customScrollView.setVisibility(View.VISIBLE);
customScrollView.addView(mView);
break;
case SCROLLVIEW: //系统scrollview,内部listview不可滑动,必须完全显示
scrollView.setVisibility(View.VISIBLE);
scrollView.addView(mView);
break;
case LINEARLAYOUT: //linearlayout
linearLayout.setVisibility(View.VISIBLE);
linearLayout.addView(mView);
mView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
break;
}
}
watcher = new MyTextWatcher();
setHandler();
initView();
initData();
}
/**
* 选择横竖屏显示,重写此方法可以更改,这里默认为竖屏
*
* @return true 为横屏, false 为竖屏
*/
public boolean getScreen_exchange() {
return false;
}
/**
* [选择页面类型是否可滑动]
*
* @return
*/
public abstract LayoutSelect selectView();
/**
* [绑定视图]
*
* @return
*/
public abstract View bindView();
/**
* [绑定布局]
*
* @return
*/
public abstract int bindLayout();
/**
* 获取标题栏实例 ,当不需要title栏的时候可以隐藏
*
* @return
*/
public RelativeLayout getTitleLayout() {
return (RelativeLayout) findViewById(R.id.title_layout);
}
/**
* 设置左侧图片显示内容并设定点击事件
*
* @return
*/
public void setTitleLeftImg(int resID) {
ImageView imageView = (ImageView) findViewById(R.id.title_img_left);
imageView.setVisibility(View.VISIBLE);
imageView.setOnClickListener(this);
imageView.setImageResource(resID);
}
/**
* 设置右上角文本名称
*
* @param text 需要显示的文本
*/
public void setRightText(String text) {
TextView textView = (TextView) findViewById(R.id.title_text_right);
textView.setVisibility(View.VISIBLE);
textView.setText(text);
textView.setOnClickListener(this);
}
/**
* 设置右上角文本名称,并带有图片
*
* @param text 需要显示的文本
* @param leftImage 文本左侧图片,没有为null
* @param rightImage 文本右侧图片,没有为null
*/
public void setRightTextImage(String text, int leftImage, int rightImage) {
TextView textView = (TextView) findViewById(R.id.title_text_right);
textView.setOnClickListener(this);
textView.setVisibility(View.VISIBLE);
textView.setText(text);
Drawable left = null;
Drawable right = null;
try {
if (leftImage != 0 && rightImage != 0) {
left = getResources().getDrawable(leftImage);
right = getResources().getDrawable(rightImage);
//必须设置图片大小,否则不显示【0,0表示坐标x,y坐标,50,50表示宽高】
//四个参数分别表示文本左、上、右、下四个方向上的图片,null表示没有图片
left.setBounds(0, 0, 30, 30);
right.setBounds(0, 0, 30, 30);
} else if (leftImage != 0) {
left = getResources().getDrawable(leftImage);
left.setBounds(0, 0, 30, 30);
} else if (rightImage != 0) {
right = getResources().getDrawable(rightImage);
right.setBounds(0, 0, 30, 30);
}
textView.setCompoundDrawables(left, null, right, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置标题栏名称
*
* @param text 需要显示的标题名
*/
public void setTitleName(String text) {
TextView textView = (TextView) findViewById(R.id.title_name);
textView.setText(text);
}
/**
* 设置右侧图片显示内容并设定点击事件
*
* @return
*/
public void setTitleRightImg(int resID) {
ImageView imageView = (ImageView) findViewById(R.id.title_img_right);
imageView.setVisibility(View.VISIBLE);
imageView.setOnClickListener(this);
imageView.setImageResource(resID);
}
/**
* 添加初始化布局,必须实现
*/
protected abstract void initView();
/**
* 添加初始化数据,必须实现
*/
public abstract void initData();
/**
* [初始化参数]
*
* @param parms
*/
public abstract void initParms(Bundle parms);
/**
* [简化Toast]
*
* @param msg
*/
protected void showToast(String msg) {
Toast.makeText(BaseActivity.this, msg, Toast.LENGTH_SHORT).show();
}
/**
* [页面跳转]
*
* @param clz
*/
public void startActivity(Class<?> clz) {
intent = new Intent(BaseActivity.this, clz);
startActivity(intent);
}
/**
* [携带数据的页面跳转]
*
* @param clz
* @param bundle
*/
public void startActivity(Class<?> clz, Bundle bundle) {
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 = new Intent();
intent.setClass(this, cls);
if (bundle != null) {
intent.putExtras(bundle);
}
startActivityForResult(intent, requestCode);
}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span>*自定一定handler,后面贴代码
<span style="white-space:pre"> </span>*/
protected UIHandler handler = new UIHandler(Looper.getMainLooper());
private void setHandler() {
handler.setHandler(new UIHandler.UIHandlerListener() {
public void UISendMessage(Message msg) {
baseHandle(msg);
}
});
}
protected abstract void baseHandle(Message msg);
/**
* 通过资源id获取string
*
* @param resId
* @return
*/
public String getBaseString(int resId) {
return getResources().getString(resId);
}
/**
* 通过资源id获取color
*
* @param resId
* @return
*/
public int getBaseColor(int resId) {
return getResources().getColor(resId);
}
/**
* 通过资源id获取drawable
*
* @param resId
* @return
*/
public Drawable getBaseDrawable(int resId) {
return getResources().getDrawable(resId);
}
/**
* 当使用了自定义上拉加载,下拉刷新 的XListView时,加载或刷新完成时调用
*
* @param xListView
*/
public void stopLoad(XListView xListView) {
xListView.stopRefresh();
xListView.stopLoadMore();
xListView.setRefreshTime("刚刚");
}
/**
* 选择器
*
* @param list 显示的列表内容
* @param kefu 客服电话
* @param bundle 携带信息
*/
public void creatPop(List<String> list, String kefu, final Bundle bundle) {
final ImageView mView = (ImageView) findViewById(R.id.title_img_right);
basePopWindow = new SelectPicPopupWindow(PopWindowEnum.KEFU_COMPLAINT, this, list, new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int postion, long l) {
TextView text = (TextView) view;
String str = text.getText().toString();
if (str.equals("客服")) {//客服
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + "10086");
intent.setData(data);
startActivity(intent);
} else if (str.equals("投诉")) {//投诉
startActivity(ComplaintActivity.class, bundle);
}
basePopWindow.dismiss();
}
}, mView.getWidth());
basePopWindow.showAsDropDown(mView, -10, -10);
}
@Override
protected void onResume() {
super.onResume();
new Thread(new Runnable() {
@Override
public void run() {
Message msg;
if (watcher != null) {
Log.e("onResume", "开始监听");
while (isWatcher) {
try {
if (watcher.getHasEmpty() || isOtherWatcher) { //只有全部为false才是数据填写完毕
msg = handler.obtainMessage();
msg.what = 10001;
handler.sendMessage(msg);
} else {
msg = handler.obtainMessage();
msg.what = 10002;
handler.sendMessage(msg);
}
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
Log.e("onResume", "监听失败");
}
}
}).start();
}
@Override
protected void onPause() {
super.onPause();
isWatcher = false;
}
/**
* 点击按钮,使用textview,有三个状态,不可点击,未点击,点击
* @param msgWhat
* @param view
*/
protected void textViewWatcher(int msgWhat, TextView view) {
switch (msgWhat) {
case 10001: //有空数据
view.setClickable(false);
view.setSelected(true);
break;
case 10002: //填写完毕
view.setClickable(true);
view.setSelected(false);
break;
}
}
}
布局文件 activity_main
基本所有的页面都有一个标题栏.所以,标题栏都直接写在页面上了.当然.这样会多用2层布局,不建议这样做,我就是太懒了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:focusable="true"
android:background="@color/white"
android:focusableInTouchMode="true"
tools:context="com.corncq.dxcx_user.MainActivity">
<include layout="@layout/title_layout"></include>
<LinearLayout android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:background="@color/white"
android:orientation="vertical">
</LinearLayout>
<com.corncq.view.CustomScrollView android:id="@+id/customScrollView"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:scrollbars="none"
>
</com.corncq.view.CustomScrollView>
<ScrollView android:id="@+id/scrollView"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:scrollbars="none">
</ScrollView>
</LinearLayout>
这里出现了一个自定义的CustomScrollView,作用是内部的listview也可以上下滑动,而外部的也可以滑动,有需要的可以自己去百度
自定的UIHandler,直接把数据请求写进去了,可以使用反射确定是否获取到所需要的必要数据,
/**
* Created by xiione on 2016/9/21.
* handler工具
*/
public class UIHandler<T> extends Handler {
private UIHandlerListener listener;
private StringBuffer buffer;
public UIHandler(Looper looper) {
super(looper);
buffer = new StringBuffer();
}
public UIHandler(Looper looper, UIHandlerListener listener) {
super(looper);
this.listener = listener;
buffer = new StringBuffer();
}
public void setHandler(UIHandlerListener listener) {
this.listener = listener;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (listener != null) {
listener.UISendMessage(msg);
}
}
/**
* @param httpUrl 路径
* @param params 接口需要的数据
* @param context 上下文
* @param tClass 反射类
* @param mList 不能为空的字段名集合
* @param msgWhat msg.what,确定返回值
* @return
*/
public void handleHttpRequest(String httpUrl, String params, Context context, Class<T> tClass, List<String> mList, int msgWhat) {
Message msg = this.obtainMessage();
try {
String data = HttpConnection.request(httpUrl, params, context);
Object object = new Gson().fromJson(data, tClass);
if (!myIterator(object, mList)) {
msg.what = 400;
this.handleMessage(msg);
return;
} else {
msg.what = msgWhat;
msg.obj = object;
this.handleMessage(msg);
return;
}
} catch (Exception e) {
e.printStackTrace();
msg.what = 400;
this.handleMessage(msg);
}
}
/**
*本地测试,不需要服务器,自己使用代码进行测试
* @param data json 字符串
* @param tClass 反射的类
* @param mList 不为空的字段名
* @param msgWhat msg.what,
*/
public void myTest(String data, Class<T> tClass, List<String> mList, int msgWhat) {
Message msg = this.obtainMessage();
try {
Log.e("myTest", "开始------");
Object object = new Gson().fromJson(data, tClass);
//当有不能为空的字段为空时,msg.what = 400;
if (!myIterator(object, mList)) {
Log.e("错误", "错误=======");
msg.what = 400;
this.handleMessage(msg);
} else {
Log.e("解析成功", "-----------");
msg.what = msgWhat;
msg.obj = object;
this.handleMessage(msg);
}
Log.e("myTest", "开始------");
} catch (Exception e) {
e.printStackTrace();
msg.what = 400;
this.handleMessage(msg);
}
}
/**
* 迭代器,用反射找到一个类中所有的内部类
*
* @param object 需要反射的类的对象实例
* @param mList 不能为空的字段名
*/
private boolean myIterator(Object object, List<String> mList) throws NoSuchMethodException, IllegalAccessException, InstantiationException {
Class mClass = object.getClass();
Log.e("看看这个类名", "就是这个==" + mClass.getName());
Field[] fd = mClass.getDeclaredFields();
for (Field field : fd) {
//获取属性名称
String name = field.getName();
//打破封装
field.setAccessible(true);
Object obj = field.get(object);
//判断该属性是否为空
if (null == obj || "".equals(obj.toString())) {
buffer.append(name + ", ");
//如果为空,与传入的不能为空的字段比较
for (String str : mList) {
//如果相同,则返回false,表示数据加载错误
if (str.equals(name)) {
return false;
}
}
}
//判断属性是否包含 data字段(自己把所有的内部类都命名带有Data,由于驼峰命名,有不想写太多判断,使用"ata"),如果有,则该属性为对象,需要继续判断
if (name.contains("ata")) {
if (!myIterator(obj, mList)) {
return false;
}
}
}
return true;
}
public String getNullName() {
return buffer.toString();
}
public interface UIHandlerListener {
void UISendMessage(Message msg);
}
产品经理要求有输入或者选择器的页面如果有提交功能的按钮,则需所有的数据填写清楚才能点击,所以写了一个监听功能的工具,感觉还不错
/**
* Created by xiione on 2016/9/29.
* 文本框与输入框输入监听,电话号码格式判断,
*/
public class MyTextWatcher implements TextWatcher {
private List<TextView> mList; //需要判空的textview与editText的集合
private boolean hasEmpty = true; //判断是否有空值
public List<TextView> getmList() {
return mList;
}
public MyTextWatcher() {
mList = new ArrayList<>();
}
public boolean isEmpty() {
for (int i = 0; i < mList.size(); i++) {
if (mList.get(i).getText().toString().isEmpty()) {
return true;
}
}
return false;
}
/**
* 添加textview与edittext,并添加事件
* @param textView
*/
public void addTextView(TextView textView) {
mList.add(textView);
textView.addTextChangedListener(this);
}
public void deleteTextView(TextView textView){
mList.remove(textView);
}
/**
* 获取空值状态
*
* @return
*/
public boolean getHasEmpty() {
return hasEmpty;
}
/**
* edittext使用,用于,edittext获取焦点时,提示文字消失
*
* @param mInfo
*/
public static void setEditText(EditText mInfo) {
mInfo.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
Log.e("获取焦点", "输入框获取焦点");
EditText _v = (EditText) v;
if (!hasFocus) {// 失去焦点
_v.setHint(_v.getTag().toString());
} else {
String hint = _v.getHint().toString();
_v.setTag(hint);
_v.setHint("");
}
}
});
}
/**
* 电话号码监听
*
* @param context
* @param mInfo
*/
public static void setPhoneEdit(final Context context, final EditText mInfo) {
mInfo.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("电话号码获取焦点", "电话号码输入框获取焦点");
EditText _v = (EditText) view;
if (!b) {// 失去焦点
_v.setHint(_v.getTag().toString());
if (!isMobileNO(mInfo.getText().toString())) {
Toast.makeText(context, "电话号码格式错误", Toast.LENGTH_SHORT).show();
mInfo.setText("");
}
} else {
String hint = _v.getHint().toString();
_v.setTag(hint);
_v.setHint("");
}
}
});
}
/**
* 验证码监听
*
* @param context
* @param mInfo
*/
public static void setCodeEdit(final Context context, final EditText mInfo) {
mInfo.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
Log.e("验证码获取焦点", "验证码输入框获取焦点");
EditText _v = (EditText) view;
if (!b) {// 失去焦点
_v.setHint(_v.getTag().toString());
if (mInfo.getText().toString().length() != 6) {
Toast.makeText(context, "请输入6位验证码", Toast.LENGTH_SHORT).show();
mInfo.setText("");
}
} else {
String hint = _v.getHint().toString();
_v.setTag(hint);
_v.setHint("");
}
}
});
}
/**
*验证手机格式
*/
public static boolean isMobileNO(String mobiles) {
/*
移动:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188
联通:130、131、132、152、155、156、185、186
电信:133、153、180、189、(1349卫通)
总结起来就是第一位必定为1,第二位必定为3或5或8,其他位置的可以为0-9
*/
String telRegex = "[1][358]\\d{9}";//"[1]"代表第1位为数字1,"[358]"代表第二位可以为3、5、8中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
if (TextUtils.isEmpty(mobiles)) return false;
else return mobiles.matches(telRegex);
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
hasEmpty = isEmpty();
}
}
好了,基本就这样了,代码简单也不用解释了,直接就能看懂,现在感觉还行,不知道以后自己看会是个什么样子的,哎,有点期待