ElaineMOMO——智能短信 相关技术总结
1、src中的目录结构
- activity.base ————–存放基本activity,方便activity.ui中的activity继承
- activty.ui —————–存放activity
- adapter ——————–存放adapter
- bean ———————-存放实体bean的创建
- dao ————————进行数据库相关的操作包
- dialog———————-对话框
- fragment——————–存放fragment
- globle———————-定义全局变量
- provider——————–存放provider
- receiver——————–存放receiver
- utils———————–存放自定义辅助类or方法
1.2、activity.base 包中关键类与代码说明
activity.base包中包含的类有:
BaseActivity.java
package com.elainemomo.activity.base;
....
public abstract class BaseActivity extends FragmentActivity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();//初始化布局组件
initData();//初始化数据
initListener();//初始化侦听
}
public abstract void initView();
public abstract void initData();
public abstract void initListener();
public abstract void processClick(View v);
@Override
public void onClick(View v) {
processClick(v);//具体点击事件的处理
}
BaseFragment.java
package com.elainemomo.activity.base;
....
public abstract class BaseFragment extends Fragment implements OnClickListener {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return initView(inflater, container, savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
initListener();
}
public abstract View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
public abstract void initListener();
public abstract void initData();
public abstract void processClick(View v);
@Override
public void onClick(View v) {
processClick(v);
}
}
MainPagerAdapter.java
public class MainPagerAdpter extends FragmentPagerAdapter {
List<Fragment> fragments;
public MainPagerAdpter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
//返回的fragment会作为viewPager的条目显示出来,就相当于ViewPager容器中每个可以动态滑动的页面
@Override
public Fragment getItem(int location) {
return fragments.get(location);
}
@Override
public int getCount() {
return fragments.size();
}
}
2、utils包中的重点知识
CursorUtils.java
public class CursorUtils {
public static void printCursor(Cursor cursor){
LogUtils.i(cursor,"一共有"+ cursor.getCount()+"行");
while(cursor.moveToNext()){
for(int i=0; i<cursor.getColumnCount();i++){
String columnName = cursor.getColumnName(i);
String content = cursor.getString(i);
LogUtils.i(cursor, columnName+" : "+content);
}
LogUtils.i(cursor, "===============================");
}
}
}
LogUtils.java
public class LogUtils {
public static boolean isDug = true;
public static void i(String tag,String msg){
if(isDug){
Log.i(tag, msg);
}
}
public static void i(Object tag,String msg){
if(isDug){
Log.i(tag.getClass().getSimpleName(), msg);
}
}
public static void e(String tag,String msg){
if(isDug){
Log.i(tag, msg);
}
}
public static void e(Object tag,String msg){
if(isDug){
Log.i(tag.getClass().getSimpleName(), msg);
}
}
}
ToastUtils.java
public class ToastUtils {
public static void showToast(Context context,String msg){
Toast.makeText(context, msg, 0).show();
}
}
3、数据库知识
实例代码:
public List<Integer> selectedConversationIds = new ArrayList<Integer>();
private boolean isSelectMode = false;
public boolean isSelectMode() {
return isSelectMode;
}
public void setSelectMode(boolean isSelectMode) {
this.isSelectMode = isSelectMode;
}
public List<Integer> getSelectedConversationIds() {
return selectedConversationIds;
}
public ConversationListAdapter(Context context, Cursor c) {
super(context, c);
notifyDataSetChanged();//重新刷新界面,数据库改变,前台就会改变
}
//返回的view对象就是Listview的条目
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return View.inflate(context, R.layout.item_conversation_list, null);
}
//设置listview每个条目显示的内容
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = getHolder(view);
Conversation conversation = Conversation.createFromCursor(cursor);
if(isSelectMode){
holder.iv_check.setVisibility(View.VISIBLE);
if(selectedConversationIds.contains(conversation.getThread_id())){
holder.iv_check.setBackgroundResource(R.drawable.common_checkbox_checked);
}else{
holder.iv_check.setBackgroundResource(R.drawable.common_checkbox_normal);
}
}
else{
holder.iv_check.setVisibility(View.GONE);
}
//设置短信内容
holder.tv_conversation_body.setText(conversation.getSnippet());
String name = ContactDao.getNameByAddress(conversation.getAddress(), context.getContentResolver());
if(TextUtils.isEmpty(name)){
holder.tv_conversation_address.setText(conversation.getAddress()+"("+conversation.getMsg_count()+")");
}
else{
holder.tv_conversation_address.setText(name+"("+conversation.getMsg_count()+")");
}
//显示时间
if(DateUtils.isToday(conversation.getDate())){
//如果是当前的时间,就显示时分
holder.tv_conversation_date.setText(DateFormat.getTimeFormat(context).format(conversation.getDate()));
}
else{
//如果不是当前的时间,就显示年月日
holder.tv_conversation_date.setText(DateFormat.getDateFormat(context).format(conversation.getDate()));
}
//设置头像
Bitmap avatar = ContactDao.getAvatarByAddress(conversation.getAddress(), context.getContentResolver());
if(avatar != null){
holder.iv_conversation_avatar.setBackgroundDrawable(new BitmapDrawable(avatar));
}
else{
holder.iv_conversation_avatar.setBackgroundResource(R.drawable.img_default_avatar);
}
}
private ViewHolder getHolder(View view){
//先判断条目view对象中是否有holder
ViewHolder holder = (ViewHolder) view.getTag();
if(holder == null){
//如果没有,就创建一个,并存入view对象
holder = new ViewHolder(view);
view.setTag(holder);
}
return holder;
}
class ViewHolder{
private ImageView iv_conversation_avatar;
private TextView tv_conversation_address;
private TextView tv_conversation_body;
private TextView tv_conversation_date;
private ImageView iv_check;
//参数就是条目的view对象
public ViewHolder(View view){
iv_conversation_avatar = (ImageView) view.findViewById(R.id.iv_conversation_avatar);
tv_conversation_address = (TextView) view.findViewById(R.id.tv_conversation_address);
tv_conversation_body = (TextView) view.findViewById(R.id.tv_conversation_body);
tv_conversation_date = (TextView) view.findViewById(R.id.tv_conversation_date);
iv_check = (ImageView)view.findViewById(R.id.iv_check);
}
}
/**
* 把选中的条目存入集合中
* @param position
*/
public void selectSingle(int position){
Cursor cursor = (Cursor) getItem(position);
Conversation conversation = Conversation.createFromCursor(cursor);
if(selectedConversationIds.contains(conversation.getThread_id())){
selectedConversationIds.remove((Integer)conversation.getThread_id());
}
else{
selectedConversationIds.add(conversation.getThread_id());
}
notifyDataSetChanged();
}
public void selectAll(){
Cursor cursor = getCursor();
//因为这里拿到的cursor的索引是随机的,所以要自己先定好位
cursor.moveToPosition(-1);
selectedConversationIds.clear();
while(cursor.moveToNext()){
Conversation conversation = Conversation.createFromCursor(cursor);
selectedConversationIds.add(conversation.getThread_id());
}
}
public void cancelAll(){
selectedConversationIds.clear();
notifyDataSetChanged();//界面刷新
}
}
1、 使用CursorAdapter
CursorAdapter这个类是继承于BaseAdapter的它是一个虚类它为Cursor和ListView连接提供了桥梁
继承CursorAdapter之后,会重写它的两个方法:newView()和bindView()
newView():对布局中的View**组件**进行设置
bindView():对获取的内容进行处理
2、使用ViewHolder内部类
class ViewHolder{….}内部类中存放的是初始liste_item中的View参数
然后再设计一个 public ViewHolder getViewHolder(View v)方法来获取holder
这种组合很经典,以后经常用到。
3、dao操作和bean实体类结合
bean中存储的是实体类的定义,简单,但是这次不同点是:
bean中不再写构造方法,而是使用一个公有静态的方法,用这个方法去创建实体类,并传送数据。这主要是可以充分利用到cursor,如下:
/**
* 创建会话bean对象
* @param cursor
* @return
*/
public static Conversation createFromCursor(Cursor cursor){
Conversation conversation = new Conversation();
conversation.setSnippet(cursor.getString(cursor.getColumnIndex("snippet")));
conversation.setThread_id(cursor.getInt(cursor.getColumnIndex("_id")));//因为CursorAdapter中必须需要一个_id的标志,才能进行查询
conversation.setMsg_count(cursor.getString(cursor.getColumnIndex("msg_count")));
conversation.setAddress(cursor.getString(cursor.getColumnIndex("address")));
conversation.setDate(cursor.getLong(cursor.getColumnIndex("date")));
return conversation;
}
dao包类的操作,就是对数据进行增删查改
这里对查询数据的URI有两种形式,一种是对自定义数据库查询,一种是对系统数据库查询
ElaineMoMo中利用到的系统数据库的URI有:
根据电话号码,查找对于的名字:
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, address);
Cursor cursor = resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME}, null, null, null);
根据电话号码,查找对于的_id:
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, address);
Cursor cursor = resolver.query(uri, new String[]{PhoneLookup._ID}, null, null, null);
获取联系人照片:
//获取联系人照片
InputStream is = Contacts.openContactPhotoInputStream(resolver,Uri.withAppendedPath(Contacts.CONTENT_URI, _id));
插入短信内容:
context.getContentResolver().insert(Contant.URI.URI_SMS, values);
4、使用异步查询SimpleAnsyQueryHandler
public class SimpleAnsyQueryHandler extends AsyncQueryHandler {
public SimpleAnsyQueryHandler(ContentResolver cr) {
super(cr);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
// CursorUtils.printCursor(cursor);
if(cookie != null && cookie instanceof CursorAdapter){
((CursorAdapter)cookie).changeCursor(cursor);
}
}
}
5、使用内容提供者Provider
使用UriMatcher对uri进行匹配
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
{
//uri的匹配规则
//authority为主机名,path为后接的路径,code
matcher.addURI(authority, "group/insert", CODE_GROUPS_INSERT);
matcher.addURI(authority, "group/query", CODE_GROUPS_QUERY);
matcher.addURI(authority, "group/update", CODE_GROUPS_UPDATE);
matcher.addURI(authority, "group/delete", CODE_GROUPS_DELETE);
....
}
在内容提供者中创建自定义数据库的实例
....
GroupOpenHelper helper;
private SQLiteDatabase db;
....
@Override
public boolean onCreate() {
//创建数据库
helper = GroupOpenHelper.getInstance(getContext());
db = helper.getWritableDatabase();
return false;
}
重写增删查改方法:
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
switch (matcher.match(uri)) {
case CODE_GROUPS_QUERY:
Cursor cursor = db.query("groups", projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), BASE_URI);
return cursor;
...
default:
throw new IllegalArgumentException("未识别的uri:"+uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
switch (matcher.match(uri)) {
case CODE_GROUPS_INSERT:
....
default:
throw new IllegalArgumentException("未识别uri:"+uri);
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
switch (matcher.match(uri)) {
case CODE_GROUPS_DELETE:
int number = db.delete("groups", selection, selectionArgs);
getContext().getContentResolver().notifyChange(BASE_URI, null);
return number;
....
default:
throw new IllegalArgumentException("未识别uri:"+uri);
}
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch (matcher.match(uri)) {
case CODE_GROUPS_UPDATE:
int number = db.update("groups", values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(BASE_URI, null);
return number;
....
default:
throw new IllegalArgumentException("未识别uri:"+uri);
}
}
6、使用SQLiteOpenHelper 创建自定义数据库
注意:这里采用了单例模式
public class GroupOpenHelper extends SQLiteOpenHelper {
/**
* 保证内存中只有一个这样的数据库实例,所以使用单例模式
* 单例模式的特点是:构造函数是私有的;私有静态实例参数;公有静态的getInstance的方法
*/
private static GroupOpenHelper instance;
public static GroupOpenHelper getInstance(Context context){
if(instance == null){
instance = new GroupOpenHelper(context, "group.db", null, 1);
}
return instance;
}
private GroupOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//sqlite里面创建表的字段类型中数值型的只有integer,没有long等类型,而且要注意最后一个字段后面不能添加逗号,否则会报错
//创建group表
db.execSQL("create table groups("
+ "_id integer primary key autoincrement,"
+ "name varchar,"
+ "create_date integer,"
+ "thread_count integer"
+ ")");
//创建会话和群组的映射表
db.execSQL("create table thread_group("
+ "_id integer primary key autoincrement,"
+ "group_id integer,"
+ "thread_id integer"
+ ")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
7、数据库操作注意事项
查询之后得到的cursor要注意填上一句:cursor.moveToFirst();或者cursor.moveTo***,否则结果将不呈现or报错
3、Dialog框架包
BaseDialog.java:
public abstract class BaseDialog extends AlertDialog implements android.view.View.OnClickListener {
protected BaseDialog(Context context) {
super(context,R.style.BaseDialog);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
initView();
initData();
initListener();
}
public abstract void initView();
public abstract void initData();
public abstract void initListener();
public abstract void processClick(View v);
@Override
public void onClick(View v) {
processClick(v);
}
}
ConfimDialog.java:
public class ConfimDialog extends BaseDialog {
private String title;
private String message;
private TextView tv_dialog_message;
private TextView tv_dialog_title;
private Button bt_dialog_cancel;
private Button bt_dialog_confirm;
private OnConfimListener onConfimListener;
public OnConfimListener getOnConfimListener() {
return onConfimListener;
}
public void setOnConfimListener(OnConfimListener onConfimListener) {
this.onConfimListener = onConfimListener;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
protected ConfimDialog(Context context) {
super(context);
}
public static void showDialog(Context context,String title,String message,OnConfimListener onConfimListener){
ConfimDialog confimDialog = new ConfimDialog(context);
confimDialog.setTitle(title);
confimDialog.setMessage(message);
confimDialog.setOnConfimListener(onConfimListener);
confimDialog.show();
}
@Override
public void initView() {
setContentView(R.layout.dialog_confim);
tv_dialog_message = (TextView) findViewById(R.id.tv_dialog_message);
tv_dialog_title = (TextView) findViewById(R.id.tv_dialog_title);
bt_dialog_cancel = (Button) findViewById(R.id.bt_dialog_cancel);
bt_dialog_confirm = (Button) findViewById(R.id.bt_dialog_confirm);
}
@Override
public void initData() {
tv_dialog_message.setText(message);
tv_dialog_title.setText(title);
}
@Override
public void initListener() {
bt_dialog_cancel.setOnClickListener(this);
bt_dialog_confirm.setOnClickListener(this);
}
@Override
public void processClick(View v) {
switch (v.getId()) {
case R.id.bt_dialog_cancel:
if(onConfimListener != null){
onConfimListener.onCancel();
}
break;
case R.id.bt_dialog_confirm:
if(onConfimListener != null){
onConfimListener.onConfim();
}
break;
default:
break;
}
dismiss();
}
//设置监听接口
public interface OnConfimListener{
void onCancel();
void onConfim();
}
}
deleteMsgDialog.java:
public class DeleteMsgDialog extends BaseDialog {
private TextView tv_deletemsg_title;
private ProgressBar pb_deletemsg;
private Button bt_deletemsg_cancel;
private int maxProgress;
private OnDeleteCancelListener onDeleteCancelListener;
protected DeleteMsgDialog(Context context,int maxProgress,OnDeleteCancelListener onDeleteCancelListener) {
super(context);
this.maxProgress = maxProgress;
this.onDeleteCancelListener = onDeleteCancelListener;
}
public static DeleteMsgDialog showDeleteDialog(Context context,int maxProgress,OnDeleteCancelListener onDeleteCancelListener){
DeleteMsgDialog dialog = new DeleteMsgDialog(context, maxProgress, onDeleteCancelListener);
dialog.show();
return dialog;
}
@Override
public void initView() {
setContentView(R.layout.dialog_delete);
tv_deletemsg_title = (TextView) findViewById(R.id.tv_deletemsg_title);
pb_deletemsg = (ProgressBar) findViewById(R.id.pb_deletemsg);
bt_deletemsg_cancel = (Button) findViewById(R.id.bt_deletemsg_cancel);
}
@Override
public void initData() {
tv_deletemsg_title.setText("正在删除(0/"+maxProgress+")");
//给进度条设置最大值
pb_deletemsg.setMax(maxProgress);
}
@Override
public void initListener() {
bt_deletemsg_cancel.setOnClickListener(this);
}
@Override
public void processClick(View v) {
switch (v.getId()) {
case R.id.bt_deletemsg_cancel:
if(onDeleteCancelListener != null){
onDeleteCancelListener.onCancel();
}
dismiss();//让对话框消失
break;
default:
break;
}
}
public interface OnDeleteCancelListener{
void onCancel();
}
/**
* 刷新进度条和标题
* @param progress
*/
public void updataProgressAndTitle(int progress){
pb_deletemsg.setProgress(progress);
tv_deletemsg_title.setText("正在删除("+progress+"/"+maxProgress);
}
}
InputDialog.java:
public class InputDialog extends BaseDialog {
private String text;
private Button bt_inputdialog_confirm;
private Button bt_inputdialog_cancel;
private EditText et_inputdialog_message;
private TextView tv_inputdialog_title;
private OnInputDialogListener onInputDialogListener;
protected InputDialog(Context context,OnInputDialogListener onInputDialogListener,String text){
super(context);
this.onInputDialogListener = onInputDialogListener;
this.text = text;
}
public static void showInputDialog(Context context,OnInputDialogListener onInputDialogListener,String text){
InputDialog inputDialog = new InputDialog(context, onInputDialogListener, text);
//为了显示软键盘:对话框默认不支持文本输入,手动把一个输入框设置为对话框的内容,Android自动对其进行设置
inputDialog.setView(new EditText(context));
inputDialog.show();
}
@Override
public void initView() {
setContentView(R.layout.dialog_input);
tv_inputdialog_title = (TextView) findViewById(R.id.tv_inputdialog_title);
et_inputdialog_message = (EditText) findViewById(R.id.et_inputdialog_message);
bt_inputdialog_cancel = (Button) findViewById(R.id.bt_inputdialog_cancel);
bt_inputdialog_confirm = (Button) findViewById(R.id.bt_inputdialog_confirm);
}
@Override
public void initData() {
tv_inputdialog_title.setText(text);
}
@Override
public void initListener() {
bt_inputdialog_cancel.setOnClickListener(this);
bt_inputdialog_confirm.setOnClickListener(this);
}
@Override
public void processClick(View v) {
switch (v.getId()) {
case R.id.bt_inputdialog_confirm:
if(onInputDialogListener != null){
onInputDialogListener.confim(et_inputdialog_message.getText().toString());
}
dismiss();
break;
case R.id.bt_inputdialog_cancel:
if(onInputDialogListener != null){
onInputDialogListener.cancel();
}
dismiss();
default:
break;
}
}
public interface OnInputDialogListener{
void cancel();
void confim(String inputMessage );
}
}
ListDialog.java:
public class ListDialog extends BaseDialog {
private String title;
private String[] items;
private TextView tv_dialoglist_title;
private ListView lv_dialog_list;
private Context context;
private OnClickListener onClickListener;
private DialogListAdapter adapter;
protected ListDialog(Context context,String title,String[] items,OnClickListener onClickListener) {
super(context);
this.context = context;
this.title = title;
this.items = items;
this.onClickListener = onClickListener;
}
public static void showListDialog(Context context,String title,String[] items,OnClickListener onItemClickListener){
ListDialog listDialog = new ListDialog(context, title, items, onItemClickListener);
listDialog.show();
}
@Override
public void initView() {
setContentView(R.layout.dialog_list);
tv_dialoglist_title = (TextView) findViewById(R.id.tv_dialoglist_title);
lv_dialog_list = (ListView) findViewById(R.id.lv_dialog_list);
}
@Override
public void initData() {
tv_dialoglist_title.setText(title);
adapter = new DialogListAdapter();
lv_dialog_list.setAdapter(adapter);
}
@Override
public void initListener() {
lv_dialog_list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(onClickListener != null){
onClickListener.onClickListener(parent, view, position, id);;
}
dismiss();
}
});
}
@Override
public void processClick(View v) {
}
class DialogListAdapter extends BaseAdapter{
private TextView tv_dialoglist_item;
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(context, R.layout.item_listdialog, null);
tv_dialoglist_item = (TextView) view.findViewById(R.id.tv_dialoglist_item);
tv_dialoglist_item.setText(items[position]);
return view;
}
}
public interface OnClickListener{
void onClickListener(AdapterView<?> parent, View view, int position, long id);
}
}
4、利用viewPager和Fragment结合,设置页面滑动页面的效果
使用FragmentPagerAdapter:
如MainPagerAdapter.java:
public class MainPageAdapter extends FragmentPagerAdapter {
List<Fragment> fragments ;
public MainPageAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
然后MainActivity.java再:
....
@Override
public void initData() {
fragments = new ArrayList<Fragment>();
ConversationFragment conversationFragment = new ConversationFragment();
GroupFragment groupFragment = new GroupFragment();
SearchFragment searchFragment = new SearchFragment();
fragments.add(conversationFragment);
fragments.add(groupFragment);
fragments.add(searchFragment);
mainPagerAdpter = new MainPagerAdpter(getSupportFragmentManager(), fragments);
viewPager.setAdapter(mainPagerAdpter);
textLightAndScale();
computeIndicateLineWidth();
}
....
5、layout布局中的重要内容
5.1 使用selector
注意:selector、shape定义的xml文件是存放在drawable文件夹下的
实例代码selector_btn_bg.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/bg_btn_pressed" android:state_pressed="true"></item>
<item android:drawable="@drawable/bg_btn_normal" android:state_pressed="false"></item>
</selector>
5.2 使用shape,自定义简单的图片外型
实例代码bg_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="8dp"/>
<solid android:color="#ffffff"/>
</shape>
5.3 使用color,自定义颜色改变
注意:color.xml是存放在values文件夹下的
实例代码:
6、监听
主要介绍:EditText中的addTextChangedListener,随着输入的内容实时改变
et_search.addTextChangedListener(new TextWatcher() {
//s:EditText中输入的参数
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
simpleAnsyQueryHandler.startQuery(0, adapter, Contant.URI.URI_SMS_CONVERSATION, projection, "body like ‘%"+s+"%‘", null, null);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
7、EditText中动态输入内容,下拉列表中可以动态显示查询的结果,并且下拉列表中的条目可以具备点击事件
例如:AutoSearchAdapter.java 继承CursorAdapter
public class AutoSearchAdapter extends CursorAdapter {
public AutoSearchAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return View.inflate(context, R.layout.item_auto_search_lv, null);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = getHolder(view);
holder.tv_auto_search_address.setText(cursor.getString(cursor.getColumnIndex("data1")));
holder.tv_auto_search_name.setText(cursor.getString(cursor.getColumnIndex("display_name")));
}
public ViewHolder getHolder(View view){
ViewHolder holder = (ViewHolder) view.getTag();
if(holder == null){
holder = new ViewHolder(view);
view.setTag(holder);
}
return holder;
}
class ViewHolder{
private TextView tv_auto_search_address;
private TextView tv_auto_search_name;
public ViewHolder(View view){
tv_auto_search_address = (TextView) view.findViewById(R.id.tv_auto_search_address);
tv_auto_search_name = (TextView) view.findViewById(R.id.tv_auto_search_name);
}
}
@Override
public CharSequence convertToString(Cursor cursor) {
return cursor.getString(cursor.getColumnIndex("data1"));
}
}
NewMsgActivity.java 中关键代码 :
@Override
public void initData() {
adapter = new AutoSearchAdapter(this, null);
et_newmsg_address.setAdapter(adapter);
adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
String[] projection = {
"data1",
"display_name",
"_id"
};
//模糊查询
String selection = "data1 like ‘%" + constraint + "%‘";
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI, projection, selection, null, null);
CursorUtils.printCursor(cursor);
//返回cursor,就是把cursor交给adapter
return cursor;
}
});
initTitleBar();
}
8、总结
这个项目还有缺少对网络编程、广播与服务、一些新特性等内容的实例操作,后续项目中注意涉及。
ElaineMOMO源码地址:https://github.com/ElaineYan489/ElaineMOMO