最近做一个登录的界面,我脑子里一下就想到QQ的登录界面,简单,美观,所以就找了些资料实现了下,现在整理下
先来看下效果图
1.首先是布局文件XML文件,不解释直接上
1>主界面
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:background="@drawable/back_groud" >
6
7 <LinearLayout
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:layout_above="@+id/login_data_layout"
11 android:layout_marginBottom="30dp"
12 android:gravity="center"
13 android:orientation="horizontal" >
14
15 <ImageView
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:src="@drawable/logo" />
19
20 </LinearLayout>
21
22 <LinearLayout
23 android:id="@+id/login_data_layout"
24 android:layout_width="match_parent"
25 android:layout_height="wrap_content"
26 android:layout_centerInParent="true"
27 android:background="@drawable/logindata_back_groud"
28 android:orientation="vertical" >
29
30 <LinearLayout
31 android:id="@+id/username_layout"
32 android:layout_width="match_parent"
33 android:layout_height="match_parent"
34 android:layout_marginLeft="10dp"
35 android:layout_marginRight="10dp"
36 android:layout_weight="1"
37 android:gravity="center_vertical"
38 android:orientation="horizontal" >
39
40 <TextView
41 android:layout_width="wrap_content"
42 android:layout_height="wrap_content"
43 android:layout_gravity="center_vertical"
44 android:layout_marginLeft="15dp"
45 android:text="账 号"
46 android:textColor="#b3b3b3"
47 android:textSize="16dp" />
48
49 <EditText
50 android:id="@+id/login_edit_userName"
51 android:layout_width="match_parent"
52 android:layout_height="wrap_content"
53 android:layout_gravity="center_vertical"
54 android:layout_marginLeft="20dp"
55 android:layout_marginRight="20dp"
56 android:layout_weight="1"
57 android:background="@null"
58 android:singleLine="true" />
59
60 <RelativeLayout
61 android:layout_width="wrap_content"
62 android:layout_height="wrap_content"
63 android:layout_weight="2.5" >
64
65 <Button
66 android:id="@+id/down_but"
67 android:layout_width="24dp"
68 android:layout_height="24dp"
69 android:layout_alignParentRight="true"
70 android:layout_marginRight="8dp"
71 android:background="@drawable/down_img" />
72 </RelativeLayout>
73 </LinearLayout>
74
75 <LinearLayout
76 android:layout_width="match_parent"
77 android:layout_height="match_parent"
78 android:layout_marginLeft="25dp"
79 android:layout_marginRight="10dp"
80 android:layout_weight="1"
81 android:gravity="center_vertical"
82 android:orientation="horizontal" >
83
84 <TextView
85 android:layout_width="wrap_content"
86 android:layout_height="wrap_content"
87 android:layout_gravity="center_vertical"
88 android:text="密 码"
89 android:textColor="#b3b3b3"
90 android:textSize="16dp" />
91
92 <EditText
93 android:id="@+id/login_edit_password"
94 android:layout_width="match_parent"
95 android:layout_height="wrap_content"
96 android:layout_gravity="center_vertical"
97 android:layout_marginLeft="20dp"
98 android:layout_marginRight="20dp"
99 android:background="@null"
100 android:inputType="textPassword"
101 android:singleLine="true" />
102 </LinearLayout>
103 </LinearLayout>
104
105 <Button
106 android:id="@+id/login_but_landing"
107 android:layout_width="match_parent"
108 android:layout_height="wrap_content"
109 android:layout_below="@+id/login_data_layout"
110 android:layout_marginTop="30dp"
111 android:background="@drawable/login_but_bg"
112 android:text="登 录"
113 android:textColor="#ffffff"
114 android:textSize="18dp" />
115
116 </RelativeLayout>
2>浮动窗口界面及其子界面
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="wrap_content"
5 android:orientation="vertical"
6 android:gravity="center_horizontal" >
7
8 <ListView
9 android:layout_width="match_parent"
10 android:layout_height="wrap_content"
11 android:id="@+id/list"
12 android:background="@drawable/list_backgroud"
13 ></ListView>
14
15
16 </LinearLayout>
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" >
5
6 <RelativeLayout
7 android:layout_width="wrap_content"
8 android:layout_height="40dp"
9 android:gravity="center_vertical" >
10
11 <Button
12 android:id="@+id/del_but"
13 android:layout_width="25dp"
14 android:layout_height="25dp"
15 android:layout_alignParentRight="true"
16 android:layout_marginRight="15dp"
17 android:background="@drawable/del_but_bg" />
18
19 <TextView
20 android:id="@+id/tv"
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_alignParentLeft="true"
24 android:layout_marginLeft="15dp"
25 android:layout_toLeftOf="@+id/del_but"
26 android:textSize="16dp" />
27 </RelativeLayout>
28
29 </LinearLayout>
2.JAVA代码
先看下类的结构,代码中基本都有注释。我就一次将代码贴出来。
1 public class LoginTest_Activity extends Activity implements Callback {
2
3 private PopupWindow mPopupWindow;// 浮动窗口
4 private UOptionsAdapter mOptionsAdapter;//适配器
5 private List<String> mUserNames;// 保存用户名
6 private List<String> mPassWords;// 保存密码
7 private List<DBLoginInfoObj> infoObjs;// 保存登陆信息数据对象
8 private LinearLayout parent;//浮动窗口依附布局
9 private int pwidth;// 浮动宽口的宽度
10
11 private EditText login_edit_userName;// 账号输入框
12 private EditText login_edit_password;// 密码输入框
13 private Button down_but;
14 private Button login_but;
15 private Handler mHandler;// 处理消息更新UI
16 private boolean init_flag = false;// 浮动窗口显示标示符
17 private static final String TBL_LOGIN_INFO = "LoginInfo";// 用户登陆信息
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_logintest);
23 // 初始化
24 this.mUserNames = new ArrayList<String>();
25 this.mPassWords = new ArrayList<String>();
26 this.infoObjs = new ArrayList<DBLoginInfoObj>();
27 this.mHandler = new Handler(this);
28 }
29
30 /**
31 * 在此方法中初始化可以获得输入框的宽度,以便于创建同样宽的浮动窗口
32 */
33 @Override
34 public void onWindowFocusChanged(boolean hasFocus) {
35 // TODO Auto-generated method stub
36 super.onWindowFocusChanged(hasFocus);
37 while (!init_flag) {
38 // 初始化UI
39 initWedget();
40 // 初始化浮动窗口
41 initPopuWindow();
42 init_flag = true;
43 }
44 }
45
46 /**
47 * 初始化UI控件
48 */
49 private void initWedget() {
50 // 浮动窗口依附的布局
51 this.parent = (LinearLayout) this.findViewById(R.id.username_layout);
52 this.login_edit_userName = (EditText) this
53 .findViewById(R.id.login_edit_userName);
54 this.login_edit_password = (EditText) this
55 .findViewById(R.id.login_edit_password);
56 this.down_but = (Button) this.findViewById(R.id.down_but);
57 login_but = (Button) this.findViewById(R.id.login_but_landing);
58 // 获取登陆数据
59 getData();
60 this.login_edit_userName.setText(this.mUserNames.get(0));
61 this.login_edit_password.setText(this.mPassWords.get(0));
62
63 // 获取地址输入框的宽度,用于创建浮动窗口的宽度
64 int w = parent.getWidth();
65 pwidth = w;
66
67 down_but.setOnClickListener(Listener_but);
68 login_but.setOnClickListener(Listener_but);
69
70 }
71
72 /**
73 * 初始化浮动窗口
74 */
75 public void initPopuWindow() {
76 // 浮动窗口的布局
77 View loginwindow = (View) this.getLayoutInflater().inflate(
78 R.layout.activity_options, null);
79 ListView listView = (ListView) loginwindow.findViewById(R.id.list);
80 // 初始化适配器
81 this.mOptionsAdapter = new UOptionsAdapter(LoginTest_Activity.this,
82 mUserNames, mHandler);
83 listView.setAdapter(mOptionsAdapter);
84 // 定义一个浮动窗口,并设置
85 this.mPopupWindow = new PopupWindow(loginwindow, pwidth,
86 LayoutParams.WRAP_CONTENT, true);
87 this.mPopupWindow.setOutsideTouchable(true);
88 this.mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
89
90 }
91
92 /**
93 * 获取登录用户名数据
94 */
95 private void getData() {
96 //获取数据对象
97 LoginInfoHandler mHandler = LoginInfoHandler
98 .create(LoginTest_Activity.this);
99 this.infoObjs = mHandler.getLoginInfoObj();
100 for (int i = 0; i < this.infoObjs.size(); i++) {
101 this.mUserNames.add(this.infoObjs.get(i).getUserName());
102 this.mPassWords.add(this.infoObjs.get(i).getPassword());
103 }
104
105 }
106
107 /**
108 * 按钮点击事件
109 */
110 OnClickListener Listener_but = new OnClickListener() {
111
112 @Override
113 public void onClick(View v) {
114 // TODO Auto-generated method stub
115 switch (v.getId()) {
116 case R.id.down_but:// 浮动地址下拉框按钮事件
117 if (init_flag) {
118 // 显示浮动窗口
119 mPopupWindow.showAsDropDown(parent, 0, -3);
120 }
121 break;
122 case R.id.login_but_landing:// 登录按钮事件
123 // 登录成功将数据保存到SQLite中
124 ContentValues values = new ContentValues();
125 String userName = login_edit_userName.getText().toString();
126 String passWord = login_edit_password.getText().toString();
127 values.put("UserName", userName);
128 values.put("PassWord", passWord);
129 DBHelper dbHelper = new DBHelper(LoginTest_Activity.this);
130 // 第一次登陆直接保存
131 if (mUserNames.size() == 0) {
132 dbHelper.insert(values, TBL_LOGIN_INFO);
133 } else {
134 // 标示符是否要插入
135 boolean flag = false;
136 // 判断当前用户名是否在数据库存在
137 LoginInfoHandler mHandler = LoginInfoHandler
138 .create(LoginTest_Activity.this);
139 List<DBLoginInfoObj> info = mHandler.getLoginInfoObj();
140 for (int i = 0; i < info.size(); i++) {
141 String username = info.get(i).getUserName();
142 if (userName.equals(username)) {
143 flag = true;
144 }
145 }
146 if (!flag) {
147 dbHelper.insert(values, TBL_LOGIN_INFO);
148 }
149 }
150 Toast.makeText(LoginTest_Activity.this, "登陆成功", 1);
151 break;
152
153 }
154
155 }
156 };
157
158 /**
159 * 处理浮动窗口传回来的数据
160 *
161 * @param msg
162 * @return
163 */
164 @Override
165 public boolean handleMessage(Message msg) {
166 // TODO Auto-generated method stub
167 Bundle bundle = msg.getData();
168 DBHelper dbHelper = new DBHelper(LoginTest_Activity.this);
169 switch (msg.what) {
170 case 1:// 根据返回的id,将数据显示在输入框中
171 int sel_id = bundle.getInt("sel_id");
172 int _id = infoObjs.get(sel_id).getID();
173 String UserName = infoObjs.get(sel_id).getUserName();
174 String PassWord = infoObjs.get(sel_id).getPassword();
175 // 先删除再插入
176 dbHelper.del(_id, TBL_LOGIN_INFO);
177 login_edit_userName.setText(UserName);
178 login_edit_password.setText(PassWord);
179 mPopupWindow.dismiss();
180 break;
181 case 2:// 根据返回的ID,删除数据
182 int del_id = bundle.getInt("del_id");
183 int id = infoObjs.get(del_id).getID();
184 dbHelper.del(id, TBL_LOGIN_INFO);
185 mUserNames.remove(del_id);
186 mOptionsAdapter.notifyDataSetChanged();
187 break;
188 }
189 return false;
190 }
1 public class UOptionsAdapter extends BaseAdapter {
2
3 private Context mContext;
4 private List<String> mDtatList;// 显示数据
5 private Handler mHandler;// 传递消息
6
7 public UOptionsAdapter(Context context, List<String> list, Handler handler) {
8 // TODO Auto-generated constructor stub
9 this.mContext = context;
10 this.mDtatList = list;
11 this.mHandler = handler;
12 }
13
14 @Override
15 public int getCount() {
16 // TODO Auto-generated method stub
17 return mDtatList.size();
18 }
19
20 @Override
21 public Object getItem(int position) {
22 // TODO Auto-generated method stub
23 return mDtatList.get(position);
24 }
25
26 @Override
27 public long getItemId(int position) {
28 // TODO Auto-generated method stub
29 return position;
30 }
31
32 @Override
33 public View getView(int position, View convertView, ViewGroup parent) {
34 // TODO Auto-generated method stub
35 ViewHolder holder = null;
36 if (convertView == null) {
37 holder = new ViewHolder();
38 convertView = LayoutInflater.from(mContext).inflate(
39 R.layout.option_item, null);
40 holder.textView = (TextView) convertView.findViewById(R.id.tv);
41 holder.button = (Button) convertView.findViewById(R.id.del_but);
42
43 convertView.setTag(holder);
44 } else {
45 holder = (ViewHolder) convertView.getTag();
46 }
47
48 // 给textView和button设置唯一标示
49 holder.textView.setTag(position);
50 holder.button.setTag(position);
51 holder.textView.setText(mDtatList.get(position));
52 holder.textView.setOnClickListener(new View.OnClickListener() {
53
54 @Override
55 public void onClick(View v) {
56 // TODO Auto-generated method stub
57 Message msg = new Message();
58 Bundle bundle = new Bundle();
59 int id = Integer.parseInt(v.getTag().toString());
60 bundle.putInt("sel_id", id);
61 msg.setData(bundle);
62 msg.what = 1;
63 mHandler.sendMessage(msg);
64 }
65 });
66
67 holder.button.setOnClickListener(new View.OnClickListener() {
68
69 @Override
70 public void onClick(View v) {
71 // TODO Auto-generated method stub
72 Message msg = new Message();
73 Bundle bundle = new Bundle();
74 bundle.putInt("del_id", Integer.parseInt(v.getTag().toString()));
75 msg.setData(bundle);
76 msg.what = 2;
77
78 mHandler.sendMessage(msg);
79
80 }
81 });
82
83 return convertView;
84 }
85
86 public class ViewHolder {
87 TextView textView;
88 Button button;
89 }
1 public class DBLoginInfoObj {
2 private int ID;// 数据库中的ID
3 private String UserName;// 账号
4 private String Password;// 密码
5
6 public int getID() {
7 return ID;
8 }
9
10 public void setID(int iD) {
11 ID = iD;
12 }
13
14 public String getUserName() {
15 return UserName;
16 }
17
18 public void setUserName(String userName) {
19 UserName = userName;
20 }
21
22 public String getPassword() {
23 return Password;
24 }
25
26 public void setPassword(String password) {
27 Password = password;
28 }
1 public class LoginInfoHandler {
2
3 private static LoginInfoHandler mHandler;
4 private Context context;
5 private static final String TBL_LOGIN_INFO = "LoginInfo";// 用户登陆信息
6 private final String PREFS_NAME = "com.example.logintestdome";
7
8 /**
9 * 私有构造函数
10 */
11 private LoginInfoHandler(Context context) {
12 this.context = context;
13 }
14
15 /**
16 * 单例模式——保证对象唯一性
17 *
18 * @return
19 */
20 public static LoginInfoHandler create(Context context) {
21 if (mHandler == null) {
22 mHandler = new LoginInfoHandler(context);
23 }
24 return mHandler;
25 }
26
27 /**
28 * 获取用户登陆信息
29 *
30 * @return
31 */
32 public List<DBLoginInfoObj> getLoginInfoObj() {
33 List<DBLoginInfoObj> infoObjs = new ArrayList<DBLoginInfoObj>();
34 DBHelper dbHelper = new DBHelper(context);
35 Cursor c = null;
36 try {
37 c = dbHelper.quertAll(TBL_LOGIN_INFO);
38 for (c.moveToLast(); !c.isBeforeFirst(); c.moveToPrevious()) {
39 DBLoginInfoObj infoObj = new DBLoginInfoObj();
40 infoObj.setID(c.getInt(c.getColumnIndex("_id")));
41 infoObj.setUserName(c.getString(c.getColumnIndex("UserName")));
42 infoObj.setPassword(c.getString(c.getColumnIndex("PassWord")));
43 infoObjs.add(infoObj);
44
45 }
46 } catch (Exception e) {
47 // TODO: handle exception
48 Log.i("数据库异常:", e.toString());
49 } finally {
50 // 关闭游标
51 c.close();
52 }
53 return infoObjs;
54 }
1 public class DBHelper extends SQLiteOpenHelper {
2
3 private static final String DB_NAME = "LoginTest.db";
4 private static final String TBL_LOGIN_INFO = "LoginInfo";// 用户IP地址
5
6 private static final String CREATE_TBL_LOGININFO = "create table LoginInfo(_id integer primary key autoincrement,UserName text,PassWord text)";
7
8
9 private SQLiteDatabase db;
10
11 public DBHelper(Context context) {
12 super(context, DB_NAME, null, 2);
13 // TODO Auto-generated constructor stub
14 }
15
16 @Override
17 public void onCreate(SQLiteDatabase arg0) {
18 // TODO Auto-generated method stub
19 // 当数据库被第一次创建时调用
20 this.db = arg0;
21 db.execSQL(CREATE_TBL_LOGININFO);
22
23 }
24
25 /**
26 * 向指定数据库中插入一条数据
27 *
28 * @param values
29 * ContentValues 键值对, 相当于map
30 * @param tableName
31 */
32 public void insert(ContentValues values, String tableName) {
33 SQLiteDatabase db = getWritableDatabase();
34 db.insert(tableName, null, values);
35 db.close();
36
37 }
38
39 /**
40 * 返回表中所有数据
41 *
42 * @param tableName
43 * @return
44 */
45 public Cursor quertAll(String tableName) {
46 Cursor c = null;
47 SQLiteDatabase db = getWritableDatabase();
48 c = db.query(tableName, null, null, null, null, null, null);
49
50 return c;
51 }
52
53 /**
54 * 根据ID删除一条数据
55 *
56 * @param id
57 * @param tableName
58 */
59 public void del(int id, String tableName) {
60
61 if (db == null)
62 db = getWritableDatabase();
63 db.delete(tableName, "_id=?", new String[] { String.valueOf(id) });
64
65 }
66
67 @Override
68 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
69 // TODO Auto-generated method stub
70
71 }