ElaineMOMO项目总结

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

时间: 2024-10-08 11:59:02

ElaineMOMO项目总结的相关文章

Win10下IIS配置、项目发布、添加网站

Win10下IIS配置 1.找到控制面板:[开始]菜单鼠标右击,打开[控制面板] 2.打开控制面板,点击[程序],点击[启用或关闭Windows功能] 下一步,点击[启用虎关闭Windows功能] 3. 开始修改IIS了,我是这样勾上的,有可能比较多. 4. 验证IIS是否正确安装,等待几分钟后IIS配置完成.在浏览器输入http://localhost/iisstart.htm会出现 IIS安装成功页面.第一次修改的时候出现了成功页面,但是后来删除了IIS中默认的网站就打不开了,但是不影响的.

使用 IDEA 创建 Maven Web 项目 (异常)- Disconnected from the target VM, address: &#39;127.0.0.1:59770&#39;, transport: &#39;socket&#39;

运行环境: JDK 版本:1.8 Maven 版本:apache-maven-3.3.3 IDEA 版本:14 maven-jetty-plugin 配置: <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <webAppSourceDirectory>${pro

MyEclipse建立SpringMVC入门HelloWorld项目

一.首先,建立空的web project项目: 1. 2. 3. 二.其次,导入先关jar包 1.将jar包导入SpringMVCHelloWorld\WebRoot\WEB-INF\lib目录下 三.接下来修改web.xml文件,在web中,指定我们的DispatcherServlet.(从这里进入SpringMVC的可控范围). 1. 2.web.xml中的内容如下: <?xml version="1.0" encoding="UTF-8"?> &l

如何用 Android Studio 导入开源项目以及常见错误的解决办法

声明:这篇文章完全来自这篇文章,感谢大神的相助.这篇文章纯粹是为了备份. 本篇以Github上最热门的MaterialDesign库,MaterialDesignLibrary来介绍怎样使用Android Sudio导入开源项目的,如果你和我一样刚刚从Eclipse转到AS,那本篇文章非常适合你. 如果不引入任何第三方库,不做自动化分渠道打包等操作,那可以在完全不了解Gradle的情况下进行Android项目的开发.但如果要想导入Github上的热门项目,必须首先熟悉Gradle. 1. Gra

【机器学习实战】Machine Learning in Action 代码 视频 项目案例

MachineLearning 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远 Machine Learning in Action (机器学习实战) | ApacheCN(apache中文网) 视频每周更新:如果你觉得有价值,请帮忙点 Star[后续组织学习活动:sklearn + tensorflow] ApacheCN - 学习机器学习群[629470233] 第一部分 分类 1.) 机器学习基础 2.) k-近邻算法 3.) 决策树 4.) 基于概率论的分类方法:朴素

git 把本地创建的项目放到github上

很早之前就注册了Github,但对其使用一直懵懵懂懂,很不熟练.直到昨天做完百度前端技术学院的task,想把代码托管到Github上的时候发现自己对于Git的操作是如此之愚钝,所以今天决定把Git好好学习一遍,好让自己以后能更好地使用Github,主要还是通过Git教程 - 廖雪峰的官方网站来学习.简要步骤可以直接看最后的总结. Git的安装就不说了. 第一步:我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创

eclipse部署tomcat修改项目访问路径(虚拟路径)

原文参考: http://www.educity.cn/wenda/147993.html http://blog.163.com/java_zf/blog/static/19926038420129240314546/ tomcat部署web项目(eclipse自动部署项目到tomcat,访问URL中不包含部署名) 最近项目中需要把项目部署到tomcat中,并且访问路径中不包含不署名,且想实现Eclipse中的自动部署,扒了好久资料,最终实现了自己的需求,呵呵,如下: 1. 把项目contex

配置resin web方式部署项目

写在前面,推荐下载resin4.0.47版本.其它版本没有测试 最近打算做一个小项目,然后容器选用了resin.想通过web提交war文件的方式 进行部署,更新代码也方便. 试了resin最新的版本(目前最新版本为4.0.53),提交war文件到webapps下面都是.tmp文件.百度google一通还是没找到解决办法. 看了下公司用的resin版本,选择4.0.47.下载后发现没最新版本的上传问题. 通过web提交war文件方式步骤如下: 步骤一:修改resin.properties.推荐配置

jsp获取当前项目跟路径

在jsp中获取当前项目的根路径: <% String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";%> 可以使用${basePath}获取.