联系人总览
效果图
SQLite数据库
建表
使用常量定义需要使用的行,方便后期更改;简洁,方便
public class Helper extends SQLiteOpenHelper { /**数据库名称*/ public static final String DataBase = "MailList.db"; public static final SQLiteDatabase.CursorFactory factory = null; public static int version = 1; /**表名*/ public static final String TableName = "Contacts"; /**行名*/ public static final String Row_LastName = "LastName"; public static final String Row_FirstName = "FirstName"; public static final String Row_PinYin = "PinYin"; public static final String Row_Phone = "PhoneNumber"; public static final String Row_School = "School"; public static final String Row_Address = "Address"; public static final String Row_Other = "Other"; public Helper(@Nullable Context context) { super( context, DataBase, factory, version ); } @Override public void onCreate(SQLiteDatabase db) { String sql = "create table " + TableName + "( "+Row_Phone+" varchar(20) primary key, "+Row_LastName+" varchar(20),"+Row_FirstName+" varchar(20),"+Row_PinYin+" varchar(20), "+Row_School+" varchar(20),"+Row_Address+" varchar(20),"+Row_Other+" varchar(20));"; db.execSQL( sql ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists "+TableName); onCreate(db); } }
CRUD
将SQLite数据库的CRUD操作封装为一个Dao类,便于管理
增
public void Insert(News news){ DB = helper.getReadableDatabase(); if (DB.isOpen()) { ContentValues values = new ContentValues(); values.put( Helper.Row_Phone,news.getPhoneNumber()); values.put( Helper.Row_LastName,news.getLastName()); values.put( Helper.Row_FirstName,news.getFirstName()); values.put(Helper.Row_PinYin,news.getPinYin()); values.put( Helper.Row_School,news.getSchool()); values.put( Helper.Row_Address,news.getAddress()); values.put(Helper.Row_Other,news.getOther()); long RowId = DB.insert(Helper.TableName,null,values); if(RowId == -1) Log.i(TAG, "数据插入失败!"); else Log.i(TAG, "数据插入成功!"+RowId); } }
删
列出根据某个字段删掉某行和删掉表中所有数据两种方法
public void Delete(String Phone){ DB = helper.getReadableDatabase(); if (DB.isOpen()){ String whereClause = "PhoneNumber = ?"; String[] whereArgs = {Phone + ""}; int count = DB.delete(Helper.TableName, whereClause, whereArgs); if (count > 0) Log.i(TAG, "删除了: " + count + "行"); else Log.i(TAG, "数据未删除!"); DB.close(); // 数据库关闭 } } public void DeleteAll(){ DB = helper.getReadableDatabase(); if (DB.isOpen()){ String whereClause = null; String[] whereArgs = null; int count = DB.delete(Helper.TableName, whereClause, whereArgs); if (count > 0) Log.i(TAG, "删除了: " + count + "行"); else Log.i(TAG, "数据未删除!"); DB.close(); // 数据库关闭 } }
改
以PhoneNumber为索引改该行的数据元素
public void Update(String PhoneNumber,String School,String Addr,String Other){ DB = helper.getReadableDatabase(); if (DB.isOpen()){ ContentValues values = new ContentValues(); values.put( Helper.Row_School,School); values.put( Helper.Row_Address,Addr); values.put(Helper.Row_Other,Other); int count = DB.update(Helper.TableName,values,"PhoneNumber = ?",new String[]{PhoneNumber}); if (count > 0){ Log.d(TAG,"update password row="+count); }else { Log.d(TAG,"update fail"); } DB.close(); } }
查
获取表中所有数据
public List<News> QueryAll() { DB = helper.getReadableDatabase(); // 获得一个只读的数据库对象 if(DB.isOpen()) { String[] columns = {Helper.Row_Phone, Helper.Row_LastName,Helper.Row_FirstName,Helper.Row_PinYin,Helper.Row_School,Helper.Row_Address,Helper.Row_Other}; // 需要的列 String selection = null; // 选择条件, 给null查询所有 String[] selectionArgs = null; // 选择条件的参数, 会把选择条件中的? 替换成数据中的值 String groupBy = null; // 分组语句 group by name String having = null; // 过滤语句 String orderBy = null; // 排序 Cursor cursor = DB.query(Helper.TableName, columns, selection, selectionArgs, groupBy, having, orderBy); String last; String first; String pinyin; String phone; String school; String addr; String other; if(cursor != null && cursor.getCount() > 0) { List<News> news = new ArrayList<News>(); while(cursor.moveToNext()) { last = cursor.getString(cursor.getColumnIndex( Helper.Row_LastName )); first = cursor.getString(cursor.getColumnIndex( Helper.Row_FirstName )); phone = cursor.getString(cursor.getColumnIndex( Helper.Row_Phone)); pinyin = cursor.getString(cursor.getColumnIndex( Helper.Row_PinYin)); school = cursor.getString(cursor.getColumnIndex(Helper.Row_School)); addr = cursor.getString(cursor.getColumnIndex( Helper.Row_Address )); other = cursor.getString( cursor.getColumnIndex( Helper.Row_Other ) ); news.add(new News(last,first,pinyin,phone,school,addr,other)); } DB.close(); return news; } if (cursor != null) { cursor.close(); } DB.close(); } return null; }
联系人分组
private void InitContacts(){ newsList = dao.QueryAll(); RemoveAll(); String curGroup = "0"; ArrayList<String> indexList = new ArrayList<>(); if (newsList != null){ for (int i = 0; i <newsList.size() ; i++) { ContactsInfo info = new ContactsInfo(newsList.get(i).getLastName()+newsList.get(i).getFirstName(),newsList.get(i).getPinYin(),newsList.get(i).getPhoneNumber(),false,false); if (!info.getGroup().equals(curGroup)) { // group 信息与保存的不一致, 那么就是该 group 的第一个 info.setIsFirstInGroup(true); // 同时将该 group 信息添加到索引中 indexList.add(info.getGroup()); // 它的上一个城市就是上一个 group 的最后一个 if (i > 0) { contactsInfoList.get(contactsInfoList.size() - 1).setIsLastInGroup(true); } curGroup = info.getGroup(); } contactsInfoList.add(info); } } }
数据库数据与滚动条绑定
SideBar.setOnTouchLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { int position = Adapter.getPositionForSection(s.charAt(0)); if (position != -1) { manager.scrollToPositionWithOffset(position, 0); } } });
添加联系人
效果图
添加紧急电话联系人
一开始添加紧急联系人的好处有两点:
- 救命稻草,时期必有急用!!!
- 防止数据库为空,避免尚未添加联系人时RecyclerView为空
数据源
public class Emergency { //lastname firstname 拼音 tel public static final String[][] PoliceTel = { {"公安","报警电话","gongan","110"}, {"火警","报警电话","huojing","119"}, {"急救中心","电话","jijiu","120"}, {"交通事故","报警电话","jiaotong","122"}}; }
添加
// 添加紧急报警电话 private void AddEmergency(){ try { newsList = dao.QueryAll(); }catch (NullPointerException e){ for (int i = 0; i < 4; i++) { dao.Insert(new News(Emergency.PoliceTel[i][0],Emergency.PoliceTel[i][1],Emergency.PoliceTel[i][2],Emergency.PoliceTel[i][3],"-","-","-")); } } }
新增
对用户输入的数据进行一下判断,然后对数据库进行插入操作。返回主界面后,对适配器进行一个刷新即可显示
private void AddContacts(){ String lastname = LastName.getText().toString(); String firstname = FirstName.getText().toString(); String pinyin = ChatExchange.getInstance().getPinyin(lastname+firstname); String phone = PhoneNumber.getText().toString(); String school = School.getText().toString(); String addr = Address.getText().toString(); String other = Other.getText().toString(); if (TextUtils.isEmpty(lastname)){ Tips.setText("姓氏不能为空"); Error.show(); return; } if (TextUtils.isEmpty(firstname)){ Tips.setText("名字不能为空"); Error.show(); return; } if (TextUtils.isEmpty(phone)){ Tips.setText("手机号码不能为空"); Error.show(); return; } if (newsList != null){ for (int i = 0; i <newsList.size() ; i++) { if (phone.equals(newsList.get(i).getPhoneNumber())){ Tips.setText("该手机号码已被绑定"); return; } } } News news = new News(lastname,firstname,pinyin,phone,school == null ? " ":school,addr == null ? " ":addr,other == null ? " ":other); dao.Insert(news); Tips.setText("插入成功"); Error.show(); }
编辑与查看联系人
查看
效果图
大图姓氏
姓氏背景是一个渐变色xml文件
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <gradient android:startColor="#BDB8B8" android:endColor="#E97878"/> </shape>
姓氏通过截取LastName字段的第一个元素,大部分LastName为一个字,单避免复姓以及乱输入等情况,就截取第一个字符。姓名就结合LastName和FirstName
LastName.setText(newsList.get(i).getLastName().substring(0,1)); Name.setText(newsList.get(i).getLastName()+newsList.get(i).getFirstName());
数据收发
发
在联系人总览界面跳转联系人详情界面时,对RecyclerView子项进行点击事件监听,并将此子项的手机号码一并传输
private void Listener(){ Adapter.setOnclick(new AllManAdapter.OnClick() { @Override public void OnClickListener(View view, int Position) { Intent intent = new Intent(ContactsActivity.this,DetailsActivity.class); String Phone = contactsInfoList.get(Position).getCityID(); intent.putExtra("PhoneNumber",Phone); startActivity(intent); } }); }
收
从主界面获取intent携带的数据,并以此为索引,遍历数据库,获取与它相关行的所有数据
PhoneNumber = getIntent().getStringExtra("PhoneNumber"); if (!TextUtils.isEmpty(PhoneNumber)){ Phone.setText(PhoneNumber); }
try{ newsList = dao.QueryAll(); }catch (NullPointerException e){ e.printStackTrace(); } if (newsList != null){ for (int i = 0; i <newsList.size() ; i++) { if (PhoneNumber.equals(newsList.get(i).getPhoneNumber())){ Address.setText(newsList.get(i).getAddress()); School.setText(newsList.get(i).getSchool()); Note.setText(newsList.get(i).getOther()); LastName.setText(newsList.get(i).getLastName().substring(0,1)); Name.setText(newsList.get(i).getLastName()+newsList.get(i).getFirstName()); } } }
编辑及删除
#### 编辑 点击编辑按钮之后,对一些EditText进行解封,以便用户可以进行编辑 ```
public void OtherThings(View view){ count++; if (count %2 == 0){ //编辑状态 UnLock(); EditMessage.setText("完成"); }else { //正常状态 Lock(); UpdateSQL(); EditMessage.setText("编辑"); } }
最后将用户修改的数据以手机号码为媒介对数据库进行更新操作
private void UpdateSQL(){ String addr = Address.getText().toString(); String school = School.getText().toString(); String node = Note.getText().toString(); dao.Update(PhoneNumber,school,addr,node); }
删除
直接以手机号码为媒介对数据库该行进行删除操作即可
dao.Delete(PhoneNumber);
拨号
申请权限
静态申请
<uses-permission android:name="android.permission.CALL_PHONE" />
动态申请
if (ActivityCompat.checkSelfPermission(DetailsActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(DetailsActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1); startActivity(intent); return; }
隐式Intent
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + PhoneNumber)); startActivity(intent);