延续大学时做课程设计的思路,首先就是登陆
当然,在登陆之前还是有其他界面的,比如第一次登陆时会有欢迎导航界面,,启动应用时会显示logo界面。下一篇再介绍。
logo界面结束之后会进入登陆界面,当然,前提是没有自动登陆的用户(有自动登陆的用户,是跳过登陆界面,直接进入主界面的)。
登陆界面由两个输入框,两个可选按钮,两个按钮组成。界面虽然简单,但是费了很大的劲处理,简单罗列如下:
在输入框的左边显示一个头像,右边是一个一键清空的小叉叉;
输入学号时会自动匹配已登录过的用户,如果登录时勾选了记住密码时,选择了用户后会自动填充密码;
当用户名或密码为空时点击登录按钮,为空的输入框会抖动,并会有红色字体提示为空;
勾选自动登陆后,下次打开应用就会直接以该用户的账户自动登陆,而不会显示登陆界面。
首先是,带有头像和叉叉的输入框
代码如下:
public class ClearEditText extends EditText implements OnFocusChangeListener, TextWatcher { /** * 删除按钮的引用 */ private Drawable mClearDrawable; /** * 控件是否有焦点 */ private boolean hasFoucs; public ClearEditText(Context context) { this(context, null); } public ClearEditText(Context context, AttributeSet attrs) { //这里构造方法也很重要,不加这个很多属性不能再XML里面定义 this(context, attrs, android.R.attr.editTextStyle); } public ClearEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { //获取EditText的DrawableRight,假如没有设置我们就使用默认的图片 mClearDrawable = getCompoundDrawables()[2]; if (mClearDrawable == null) { // throw new NullPointerException("You can add drawableRight attribute in XML"); mClearDrawable = getResources().getDrawable(R.drawable.delete_selector); } mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); //默认设置隐藏图标 setClearIconVisible(false); //设置焦点改变的监听 setOnFocusChangeListener(this); //设置输入框里面内容发生改变的监听 addTextChangedListener(this); } /** * 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件 * 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和 * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑 */ @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (getCompoundDrawables()[2] != null) { boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight()))); if (touchable) { this.setText(""); } } } return super.onTouchEvent(event); } /** * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏 */ @Override public void onFocusChange(View v, boolean hasFocus) { this.hasFoucs = hasFocus; if (hasFocus) { setClearIconVisible(getText().length() > 0); } else { setClearIconVisible(false); } } /** * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去 * @param visible */ protected void setClearIconVisible(boolean visible) { Drawable right = visible ? mClearDrawable : null; setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]); } /** * 当输入框里面内容发生变化的时候回调的方法 */ @Override public void onTextChanged(CharSequence s, int start, int count, int after) { if(hasFoucs){ setClearIconVisible(s.length() > 0); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } /** * 设置晃动动画 */ public void setShakeAnimation(){ this.setAnimation(shakeAnimation(5)); } /** * 晃动动画 * @param counts 1秒钟晃动多少下 * @return */ public static Animation shakeAnimation(int counts){ Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0); translateAnimation.setInterpolator(new CycleInterpolator(counts)); translateAnimation.setDuration(1000); return translateAnimation; } }
在定义输入框时:
<cn.edu.wit.withelper.util.ClearEditText android:id="@+id/userid" android:layout_weight="1" android:layout_width="0dip" android:layout_height="wrap_content" android:background="@drawable/et_userid_border" android:drawableLeft="@drawable/users_selector" android:drawableRight="@drawable/delete_selector" android:hint="请输入您的学号" android:inputType="number" android:focusableInTouchMode="true" android:padding="3dp" android:singleLine="true" android:textSize="25sp" />
抖动的动画也在上面定义了,
下面就介绍下拉列表,
ib_spinner = (ImageButton) findViewById(R.id.ib_spinner);//一个图片,覆盖到输入框的右端 ib_spinner.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 弹出下拉列表 ListView listView = new ListView(getApplicationContext()); listView.setCacheColorHint(0x00000000);// 滑动时 不变色 listView.setVerticalScrollBarEnabled(false); listView.setBackgroundColor(getResources().getColor(R.color.white)); //设置透明度 listView.getBackground().setAlpha(230); listView.setAdapter(new MyAdapter()); pop = new PopupWindow(listView, etUserId.getWidth()+ib_spinner.getWidth(), LayoutParams.WRAP_CONTENT, true); // pop隐藏 pop.setBackgroundDrawable(new ColorDrawable(0x00000000)); pop.setOutsideTouchable(true); pop.setFocusable(true); // pop.setAnimationStyle(R.style.PopupAnimation); pop.showAsDropDown(etUserId, 0, -8); pop.update(); } });
接下来就是,记住密码与自动登陆了
if (1 == isAuto) { //自动登录则存入数据库,且写到配置文件 SharedPreferencesUtil.saveLoginUser(LoginActivity.this, user); userInfoServices.insertUserInfo(user); }else if (1 == isRemember) { //记住密码就写入数据库 userInfoServices.insertUserInfo(user); }
登陆成功后,就根据用户的选择,对数据进行处理
然后就是,如何实现登陆
public static UserInfo login(UserInfo loginUser) { String URL = "http://www.******.com/API/Android/Login"; final Map<String, String> params = new HashMap<String, String>(); params.put("userID", loginUser.getUserId()); params.put("password", loginUser.getPassword()); JSONObject jsonResult = InterfaceUtil.getJSONObject(URL, params); if (jsonResult == null) { Log.i(TAG, "result = null"); return loginUser; } else { Log.i(TAG, "result = " + jsonResult.toString()); return getUserByJson(jsonResult, loginUser); } }
public static JSONObject getJSONObject( String url, // 请求的URL Map<String, String> params // 请求的参数序列 ) { long timestamp = new Date().getTime(); //时间戳 params.put("timestamp", "" + timestamp); //sign params.put("sign", MD5Util.getMD5String(SALT + timestamp)); String result = postRequestToServer(url, params); if (null == result) { Log.i(TAG, "result = null"); return null; }else { Log.i(TAG, "result = " + result); JSONTokener jsonTokener = new JSONTokener(result); JSONObject json = null; try { json = (JSONObject) jsonTokener.nextValue(); } catch (JSONException e) { e.printStackTrace(); } finally { return json; } }//end of else }
这里就涉及到对网络的访问,对json的解析,以及对数据的封装
public static String postRequestToServer(String url, // 请求的URL Map<String, String> params // 请求的参数序列 ) { Log.i(TAG, "访问网络"); HttpEntityEnclosingRequestBase httpRequest = new HttpPost(url); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params.size()); for (Map.Entry<String, String> entry : params.entrySet()) {// 构建表单字段内容 nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } String strResult = ""; try { httpRequest.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8")); HttpClient client = new DefaultHttpClient(); HttpParams httpparams = client.getParams(); HttpConnectionParams.setConnectionTimeout(httpparams,7000); HttpConnectionParams.setSoTimeout(httpparams,7000); // 执行请求 HttpResponse httpResponse = client.execute(httpRequest); // 判断返回结果,200则说明正确返回 if (httpResponse.getStatusLine().getStatusCode() == 200) { // 从返回的结果中获取内容 strResult = EntityUtils.toString(httpResponse.getEntity(),"UTF-8"); } else { strResult = null; } } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); msg.what = Task.ERROR_NETEXCEPTION ; msg.obj = e; MainService.handler.sendMessage(msg); strResult = null; } finally { return strResult; } }
本应用中,所有的网络访问都是通过这个函数实现的
还有一个获取网络图片的函数,在本应用中没有使用,是准备用来获取用户头像的
/** * 通过url获取图片 * @param url * @return */ public static Drawable getNetImage(URL url) { if (null == url) return null; try { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); return Drawable.createFromStream(connection.getInputStream(),"image"); } catch (IOException e) { e.printStackTrace(); } return null; }
还有一个就是对SharedPreferences的操作;
/** * 保存登录用户信息 * @param context * @param user */ public static void saveLoginUser(Context context, UserInfo user) { SharedPreferences sp = context.getSharedPreferences(LOGIN_USER, Context.MODE_PRIVATE); Editor editor = sp.edit(); editor.putString(UserInfo.USERID, user.getUserId()); editor.putString(UserInfo.SESSIONID, user.getSessionId()); editor.putString(UserInfo.USERNAME, user.getUserName()); editor.commit(); } /** * 获取登录用户信息 * @param context * @return */ public static UserInfo getLoginUser(Context context) { SharedPreferences sp = context.getSharedPreferences(LOGIN_USER, Context.MODE_PRIVATE); String userId = sp.getString(UserInfo.USERID, ""); String session = sp.getString(UserInfo.SESSIONID, ""); String userName = sp.getString(UserInfo.USERNAME, ""); if ("".equals(userId)) return null; UserInfo user = new UserInfo(); user.setUserId(userId); user.setSessionId(session); user.setUserName(userName); return user; }
登陆差不多就这么些东西,现在看来有很多东西都太low了,但还是原汁原味地展示出来。明天把项目的源码上传到github上,有时间就修改一下,希望有兴趣,或者有心赐教的大神多多指点。
ps:自动获取标签太烂了
时间: 2024-10-06 06:54:31