引言
本周我们主要进行进行页面设计与代码编写,在前两天的工作中我们主要进行了以下工作:
- 页面的初步设计与逻辑交互设计
- 客户端代码编写
- 后台代码编写
在编写登录代码之前,我和王宁先定义了一些基类:
BaseActivity为Activity定义了一个基类,内部为setContentView设置了getLayoutId抽象函数,从而使得Activity可以快速设置layout。
BaseApplication重写了Application类,因为app启动率先调用Application的onCreate函数,故重写这个函数,在里面做一些全局初始化。
BaseFragment'为Fragment定义基类,原理与BaseActivity相似。
登录界面由app logo作为大背景,使用手机号和密码进行登录,手机号和密码输入完毕后,点击登录按钮后,即可进行登录操作。
若没有账号,则点击下方的注册按钮,跳转到注册页面进行注册。
Android的界面布局文件是xml文件,android studio环境提供了图形化的布局文件编写,但考虑到该APP可能安装在不同屏幕的手机上,需要保证布局的灵活与精确性,所以主要还是采用手动编写代码的方式进行。
根据我的设计,中间的logo采用ImageView控件来实现,两个输入框采用EditText控件实现,三个按钮采用Button控件来实现,整体的布局控制选择纵向的LinearLayout,通过调整不同组件的layout_weight(即权重)属性,就可以控制组件的相对大小,可以自动适应不同尺寸的屏幕。整个界面的蓝色背景只要调整最上次LinearLayout的背景颜色就可以实现。
这一还有一个小技巧要特别说一下,两个输入框是带有图标的,而Android并没有自带的这种组件,所以我选择使用一个横向的LinearLayout,将一个ImageView和EditText放在一起,同时将该LinearLayout的背景设为绘制的椭圆,通过精细调整组件的尺寸,就可以达到理想的效果。
源代码如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/login_bg" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/login_bg" android:gravity="center" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="270dp" android:gravity="center_horizontal|bottom" android:orientation="vertical" android:padding="40dp"> <ImageView android:layout_width="wrap_content" android:layout_height="120dp" android:src="@drawable/login_logo" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="56dp" android:layout_marginRight="56dp" android:background="@drawable/edittext_blue_bord_bg" android:orientation="horizontal"> <ImageView android:layout_width="16dp" android:layout_height="16dp" android:layout_margin="16dp" android:src="@drawable/login_userid_icon" /> <EditText android:id="@+id/loginAccountEditText" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="16dp" android:background="@null" android:hint="手机号" android:textColor="@color/black" android:textColorHint="@color/text_hint_gray" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="56dp" android:layout_marginRight="56dp" android:layout_marginTop="16dp" android:background="@drawable/edittext_blue_bord_bg" android:orientation="horizontal"> <ImageView android:layout_width="16dp" android:layout_height="16dp" android:layout_margin="16dp" android:src="@drawable/login_password_icon" /> <EditText android:id="@+id/loginPasswordEditText" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="16dp" android:background="@null" android:hint="密码(6-16位英文和数字)" android:textColor="@color/black" android:textColorHint="@color/text_hint_gray" android:textSize="16sp" /> </LinearLayout> <Button android:id="@+id/loginLoginButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="56dp" android:layout_marginRight="56dp" android:layout_marginTop="16dp" android:background="@drawable/login_button_bg" android:gravity="center" android:onClick="login" android:text="登陆" android:textColor="@color/white" android:textSize="16sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="56dp" android:layout_marginRight="56dp" android:layout_marginTop="16dp" android:paddingBottom="16dp"> <Button android:id="@+id/loginForgetButton" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@color/transparent" android:gravity="center" android:text="忘记密码" android:textColor="@color/login_button_default_blue" android:textSize="16sp" /> <Button android:id="@+id/loginRegisterButton" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@color/transparent" android:gravity="center" android:onClick="goToRegister" android:text="注册" android:textColor="@color/login_button_default_blue" android:textSize="16sp" /> </LinearLayout> </LinearLayout> </LinearLayout> </LinearLayout> </LinearLayout>
二、内部处理逻辑代码的编写:
在之前的详细设计中,已经完成了登录的详细设计。
伪代码如下所示:
1.检查网络是否可用,不可用跳转到9
2.检查账户输入是否合法,不合法跳转到9
3.检查密码输入是否合法,不合法跳转到9
4.建立链表,将账户和密码存入其中
5.调用网络工具类的相应接口,等待返回结果
6.判断返回结果是否成功,不成功跳转到9
7.验证返回的用户数据是否为空,为空跳转到9
8.登录成功,跳转到主界面
9.登录失败
UML的活动图如下所示:
以此为基础,编写的代码如下所示:
package com.example.sdu.myflag.activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.*; import android.view.View.OnClickListener; import com.example.sdu.myflag.R; import com.example.sdu.myflag.base.BaseActivity; import com.example.sdu.myflag.base.BaseApplication; import com.example.sdu.myflag.util.BaseTools; import com.example.sdu.myflag.util.NetUtil; import com.example.sdu.myflag.util.NetUtil.*; import org.json.*; import java.io.IOException; import java.io.InputStream; import java.util.*; import okhttp3.Response; /** * Created by Administrator on 2016/8/17. */ public class LoginActivity extends BaseActivity { private EditText accountEditText, passwordEditText; private Button forgetButton; private String account, password; @Override public int getLayoutId() { return R.layout.activity_login; } @Override public void afterCreate(Bundle savedInstanceState) { //获取各组件id accountEditText = (EditText) findViewById(R.id.loginAccountEditText); passwordEditText = (EditText) findViewById(R.id.loginPasswordEditText); forgetButton = (Button) findViewById(R.id.loginForgetButton); setButtonListener(); } public void goToRegister(View v) { startNewActivity(RegisterActivity.class); } public void login(View v) { if (getText()) { List<Param> params = new LinkedList<Param>(); params.add(new Param("phone", account)); params.add(new Param("password", password)); LoginResult loginResult = new LoginResult(); try { NetUtil.getResult(NetUtil.loginUrl, params, loginResult); } catch (IOException e) { e.printStackTrace(); } } } //为各个按钮设置监听器 private void setButtonListener() { forgetButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); } //获取各EditText中的值,并进行合法性校验,合法返回true //不合法返回false,并用Toast进行提醒 private boolean getText() { account = accountEditText.getText().toString(); password = passwordEditText.getText().toString(); if (!BaseTools.isNetworkAvailable(LoginActivity.this)) { Toast.makeText(this, "当前网络不可用!", Toast.LENGTH_SHORT).show(); return false; } else if (account.isEmpty()) { Toast.makeText(this, "手机号不能为空!", Toast.LENGTH_SHORT).show(); return false; } else if (password.isEmpty()) { Toast.makeText(this, "密码不能为空!", Toast.LENGTH_SHORT).show(); return false; } return true; } private class LoginResult implements CallBackForResult { @Override public void onFailure(final IOException e) { LoginActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(LoginActivity.this, e.getMessage(), Toast.LENGTH_LONG).show(); } }); } @Override public void onSuccess(Response response) { if (response.isSuccessful()) { try { JSONObject jsonObject = new JSONObject(response.body().string()); String user = jsonObject.getString("user"); if (user.equals("")) { LoginActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(LoginActivity.this, "用户名或密码错误", Toast.LENGTH_LONG).show(); } }); } else { JSONObject userJson = new JSONObject(user); SharedPreferences preferences = BaseApplication.getInstance().getSharedPreferences("User", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString("uid", userJson.getInt("uid") + "").apply(); editor.putString("phone", userJson.getString("phone")).apply(); editor.putString("nickname", userJson.getString("nickname")).apply(); editor.putString("information", userJson.getString("information")).apply(); editor.putString("email", userJson.getString("email")).apply(); editor.putString("password", password).apply(); LoginActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(LoginActivity.this, "登陆成功", Toast.LENGTH_LONG).show(); } }); startNewActivity(MainActivity.class); LoginActivity.this.finish(); } } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } } } }
总结
应该说,这两天代码的编写工作进行的比较顺利,这得益于前期做了良好的界面设计和详细设计,大大减少了编码的工作量,保证了工作进度。总体来说前两天的工作进度还是可以的,希望这周剩下的时间我能够完成好剩下的任务。