Android仿QQ登錄下拉歷史列表
效果圖


我們的需求和明確,就是要把登錄成功的賬號(hào)密碼緩存保存好,然后并且顯示到歷史信息列表里面讓用戶可以自由切換已經(jīng)登錄過的賬號(hào)。
具體實(shí)現(xiàn)
我這邊是寫了一個(gè)數(shù)據(jù)模型bean類 selectphone;
package com.example.accountrecord/***?*?用戶登錄信息*/public class SelectPhone {private String account_id;private String name;private String password;private String user_type;private String token;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}public String getUser_type() {return user_type;}public void setUser_type(String user_type) {this.user_type = user_type;}public String getPassword() {return password;}public void setPassword(String password)this.password = password;}public String getAccount_id() {return account_id;}public void setAccount_id(String account_id) {this.account_id = account_id;}}
然后在將多條selectphone 存儲(chǔ)在list集合里面 使用的存儲(chǔ)方案是安卓自帶的 SharedPreferences
但是SharedPreferences 默認(rèn)只支持基礎(chǔ)數(shù)據(jù)類型 所以我們要做簡(jiǎn)單的轉(zhuǎn)換改造 將list轉(zhuǎn)成json字符串存起來(lái) 獲取的適合我們?cè)僦vjson還原成list集合
存儲(chǔ)
/*** 4.存儲(chǔ)賬本SelectPhone的list*/public static void putSelectBean(Context context, ListphoneList, String key) { if (sp == null) {sp = context.getSharedPreferences("config", MODE_PRIVATE);}SharedPreferences.Editor editor = sp.edit();Gson gson = new Gson();String json = gson.toJson(phoneList);editor.putString(key, json);editor.commit();}
讀取
/*** 讀取賬本SelectPhone的list*/public static ListgetSelectBean(Context context, String key) { if (sp == null) {sp = context.getSharedPreferences("config", MODE_PRIVATE);}Gson gson = new Gson();String json = sp.getString(key, null);Type type = new TypeToken>() {
}.getType();ListarrayList = gson.fromJson(json, type); return arrayList;}
loginActivity中具體調(diào)用存儲(chǔ)數(shù)據(jù)
private void login(){account=account_ed.getText().toString();password=password_ed.getText().toString();if(TextUtils.isEmpty(account)||TextUtils.isEmpty(password)){Toast.makeText(mContext,"賬號(hào)或者密碼輸入不能為空",Toast.LENGTH_LONG).show();}SelectPhone selectPhone=new SelectPhone();selectPhone.setName(account);selectPhone.setPassword(password);Listgetdata = SharedPreferencesUtils.getSelectBean(LoginActivity.this, "selectphone");if (getdata != null && getdata.size() > 0) {getdata.add(0,selectPhone);SharedPreferencesUtils.putSelectBean(LoginActivity.this, getdata, "selectphone");} else {data.add(selectPhone);SharedPreferencesUtils.putSelectBean(LoginActivity.this, data, "selectphone");}Toast.makeText(mContext,"登錄成功數(shù)據(jù)緩存成功",Toast.LENGTH_LONG).show();finish();}

彈出的popupwindow 具體實(shí)現(xiàn):
布局代碼
xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent">android:layout_width="300dp"android:layout_height="148.44dp"android:background="@color/activityTextWhite"android:layout_centerHorizontal="true">android:id="@+id/select_listview"android:layout_width="match_parent"android:layout_height="match_parent">
具體邏輯代碼:
/*** 自定義PopupWindow 主要用來(lái)顯示ListView** @param* @param* @create time*/public class SpinerPopWindowextends PopupWindow { private static final String TAG = "SpinerPopWindow";private LayoutInflater inflater;private ListView mListView;private Listlist; private MyAdapter mAdapter;private Context context;private RemoveUserinfoListner removeUserinfoListner;public SpinerPopWindow(Context context, Listlist, OnItemClickListener clickListener, RemoveUserinfoListner removeUserinfoListner) {super(context);inflater = LayoutInflater.from(context);this.list = list;this.context = context;this.removeUserinfoListner = removeUserinfoListner;init(clickListener);}private void init(OnItemClickListener clickListener) {//View view = inflater.inflate(R.layout.select_phonedialog, null);View view = inflater.inflate(ResourceUtil.getLayoutId(context, "select_phonedialog"), null);setContentView(view);setFocusable(true);setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);ColorDrawable dw = new ColorDrawable(0x00);setBackgroundDrawable(dw);//mListView = view.findViewById(R.id.select_listview);mListView = view.findViewById(ResourceUtil.getId(context, "select_listview"));mAdapter = new MyAdapter();if (list != null) {mListView.setAdapter(mAdapter);}mListView.setOnItemClickListener(clickListener);}private class MyAdapter extends BaseAdapter {@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView, ViewGroup parent) {final SelectPhone selectPhone = (SelectPhone) list.get(position);ViewHodler hodler = null;if (convertView == null) {convertView = LayoutInflater.from(context).inflate(ResourceUtil.getLayoutId(context,"selectphone_item"), parent, false);hodler = new ViewHodler();hodler.phonetextview = convertView.findViewById(ResourceUtil.getId(context, "account_textview"));//account_textview //account_imagehodler.imageview = convertView.findViewById(ResourceUtil.getId(context, "account_image"));hodler.deleterl = convertView.findViewById(ResourceUtil.getId(context, "delete_account_rl"));convertView.setTag(hodler);} else {hodler = (ViewHodler) convertView.getTag();}hodler.phonetextview.setText(selectPhone.getName());//操作刪除存在對(duì)象里面的數(shù)據(jù)刷新listviewhodler.deleterl.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// data.remove(position);DeleteaccountDialog deleteaccountDialog = new DeleteaccountDialog(context,selectPhone.getName(), new Deleteaccountlistener() {@Overridepublic void deleteaccountsuccess() {notifyDataSetChanged();removeUserinfoListner.removeuserinfosuccess(position,(List) list); }});deleteaccountDialog.show();}});return convertView;}public class ViewHodler {TextView phonetextview;ImageView imageview;RelativeLayout deleterl;}}}

刪除彈窗dialog的實(shí)現(xiàn):
布局文件
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent">android:layout_width="316dp"android:layout_height="180.89dp"android:layout_centerHorizontal="true"android:layout_centerVertical="true"android:background="@drawable/activity_background_white"android:orientation="vertical">android:layout_width="match_parent"android:layout_height="124.44dp"android:orientation="vertical">android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="23.11dp"android:text="刪除賬號(hào)記錄"android:textColor="@color/activityTitle"android:textSize="23.11dp"android:layout_gravity="center"/>android:id="@+id/deleteaccount_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="確認(rèn)刪除賬號(hào)[XQ123456]"android:layout_gravity="center"android:textSize="18.67dp"android:textColor="@color/activityTitle"android:layout_marginTop="24dp"/>android:layout_width="match_parent"android:layout_height="1.33dp"android:background="@color/activityTextMainClor">android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal">android:id="@+id/deleteaccount_cancel"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1">android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerHorizontal="true"android:gravity="center"android:text="取消"android:textSize="24dp"android:textColor="@color/smsedittextcolor"/>android:layout_width="1.33dp"android:layout_height="match_parent"android:background="@color/activityTextMainClor">android:id="@+id/deleteaccount_confirm"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1">android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerHorizontal="true"android:gravity="center"android:text="確定"android:textSize="24dp"android:textColor="@color/activityBlueButton"/>
邏輯代碼:
/**?*?類說(shuō)明:刪除賬號(hào)是否確認(rèn)彈窗*/public class DeleteaccountDialog extends Dialog {private Context context;private RelativeLayout cancel, confirm;private TextView accounttext;private Deleteaccountlistener deleteaccountlistener;private String account;public DeleteaccountDialog(Context context, String account, Deleteaccountlistenerdeleteaccountlistener) {super(context);this.context = context;this.account = account;this.deleteaccountlistener = deleteaccountlistener;}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getWindow().setBackgroundDrawableResource(android.R.color.transparent);getWindow().requestFeature(Window.FEATURE_NO_TITLE);LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);View layout = inflater.inflate(ResourceUtil.getLayoutId(context,"deleteaccount_dialog"), null);setContentView(layout);initview();}private void initview() {cancel = findViewById(ResourceUtil.getId(context, "deleteaccount_cancel"));confirm = findViewById(ResourceUtil.getId(context, "deleteaccount_confirm"));accounttext = findViewById(ResourceUtil.getId(context, "deleteaccount_text"));accounttext.setText("確定刪除賬號(hào)[" + account + "]");//刪除賬號(hào)取消cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {DeleteaccountDialog.this.dismiss();}});//確定刪除賬號(hào)confirm.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {DeleteaccountDialog.this.dismiss();deleteaccountlistener.deleteaccountsuccess();}});}}
我們?cè)趌oginactivity中調(diào)用自定義的popupwindow 顯示列表的時(shí)候我們要注意幾個(gè)回調(diào),首先看具體調(diào)用
getdata = SharedPreferencesUtils.getSelectBean(mContext, "selectphone");if (getdata != null && getdata.size() > 0) {SelectPhone phone = getdata.get(0);cacheaccount = phone.getName();cachepsw=phone.getPassword();if (!TextUtils.isEmpty(cacheaccount)) {account_ed.setText(cacheaccount);password_ed.setText(cachepsw);} else {account_ed.setText(null);password_ed.setText(null);}}mSpinerPopWindow = new SpinerPopWindow(LoginActivity.this, getdata, itemClickListener, removeUserinfoListner);mSpinerPopWindow.setOnDismissListener(dismissListener);
用戶點(diǎn)擊列表里面的某一條信息的回調(diào)監(jiān)聽
/*** popupwindow顯示的ListView的item點(diǎn)擊事件*/private AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView> parent, View view, int position, long id) {mSpinerPopWindow.dismiss();flag = false;SelectPhone selectPhone = getdata.get(position);String getusername = selectPhone.getName();String psw = selectPhone.getPassword();account_ed.setText(getusername);password_ed.setText(psw);}};
用戶點(diǎn)擊空白部分的監(jiān)聽:
/*** 監(jiān)聽popupwindow取消*/private PopupWindow.OnDismissListener dismissListener = new PopupWindow.OnDismissListener(){@Overridepublic void onDismiss() {????????????flag?=?false;}};
用戶點(diǎn)擊確認(rèn)刪除按鈕的監(jiān)聽:
//刪除用戶緩存信息private RemoveUserinfoListner removeUserinfoListner = new RemoveUserinfoListner() {@Overridepublic void removeuserinfosuccess(int position, Listdata) { if (data != null && data.size() > 0) {data.remove(position);SharedPreferencesUtils.putSelectBean(mContext, data, "selectphone");flag = false;Listgetdata = SharedPreferencesUtils. getSelectBean(LoginActivity.this, "selectphone");if (getdata != null && getdata.size() > 0) {SelectPhone selectPhone = getdata.get(0);account_ed.setText(selectPhone.getName());password_ed.setText(selectPhone.getPassword());} else {account_ed.setText(null);password_ed.setText(null);}} else {Toast.makeText(mContext,"緩存數(shù)據(jù)為空",Toast.LENGTH_LONG).show();}}};
我們需要在相應(yīng)的用戶操作的監(jiān)聽回調(diào)里面去更新一些UI來(lái)滿足我們的需求,最后完整的loginactivity 的布局代碼和 java邏輯代碼看demo。
到此整個(gè)仿QQ的登錄下拉歷史功能實(shí)現(xiàn)基本講完了 主要關(guān)鍵點(diǎn)是數(shù)據(jù)存儲(chǔ)的邏輯要注意, UI實(shí)現(xiàn)相對(duì)簡(jiǎn)單。
源碼地址:
https://github.com/xq19930522/accountrecord_demo
到這里就結(jié)束啦。
