15. “我”模块(一)之注册

上一节对欢迎模块进行了综述(可参见 10. 视频模块 进行了解),接下来将从视频模块开始详细介绍:

  • [“我”模块(一)之创建数据库]
  • [“我”模块(一)之“我”]
  • [“我”模块(一)之注册]
  • [“我”模块(一)之登录]
  • [“我”模块(一)之个人资料]
  • [“我”模块(一)之个人资料修改]

知识点

  • 掌握SQLite数据库的使用,能够使用数据库存储用户信息。
  • 掌握“我”界面开发,能够展示用户基本信息以及该界面的功能。
  • 掌握“登录”“注册”界面的开发,实现用户登录注册功能。
  • 掌握“个人资料”以及“修改”界面的开发,实现用户信息的展示与修改功能。

注册

任务综述:
“注册”界面主要用于输入注册消息(用户名与密码),点击“注册”按钮即可进行注册。由于头条项目把用户信息全部存放在本地,因此在注册成功后,需要将用户名和密码保存在SharedPreferences中便于后续用户登录。为了保证账户的安全,在保存密码时会采用MD5加密算法,这种算法是不可逆的,且具有一定的安全性。

7. “注册”界面

任务分析:

“注册”界面主要用于输入用户的注册信息,实现用户注册功能,界面效果如图所示。


10186693-66a79a8fa3d283a7.png
“注册”界面

任务实施:
(1)创建“注册”界面。创建RegisterActivity以及activity_register。在该布局文件中,通过<include>标签将main_title_bar.xml(标题栏)引入。

(2)导入界面图片(4个)。

(3)放置界面控件。
一个ImageViewRoundOval控件,用于显示用户默认头像;
两个EditText控件,用于输入用户名和密码;
一个ImageView控件,用于密码的显示和隐藏;
一个Button控件,作为注册按钮。

activity_register.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/register_bg_color"
    android:orientation="vertical">
    <include layout="@layout/main_title_bar" />
    <com.itheima.topline.view.ImageViewRoundOval
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="25dp"
        android:layout_marginTop="35dp"
        android:scaleType="fitXY"
        android:src="@drawable/default_head" />
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        app:cardCornerRadius="5dp"
        app:cardElevation="3dp"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="true">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <EditText
                android:id="@+id/et_user_name"
                android:layout_width="fill_parent"
                android:layout_height="48dp"
                android:layout_gravity="center_horizontal"
                android:background="@drawable/register_edittext_top_radius"
                android:drawableLeft="@drawable/user_name_icon"
                android:drawablePadding="10dp"
                android:gravity="center_vertical"
                android:hint="请输入用户名"
                android:paddingLeft="8dp"
                android:singleLine="true"
                android:textColor="#000000"
                android:textColorHint="@color/register_hint_text_color"
                android:textCursorDrawable="@null"
                android:textSize="14sp" />
            <View
                android:layout_width="fill_parent"
                android:layout_height="1dp"
                android:background="@color/divider_line_color" />
            <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">
                <EditText
                    android:id="@+id/et_psw"
                    android:layout_width="fill_parent"
                    android:layout_height="48dp"
                    android:layout_gravity="center_horizontal"
                    android:background="@drawable/register_edittext_bottom_radius"
                    android:drawableLeft="@drawable/psw_icon"
                    android:drawablePadding="10dp"
                    android:hint="请输入密码"
                    android:inputType="textPassword"
                    android:paddingLeft="8dp"
                    android:singleLine="true"
                    android:textColor="#000000"
                    android:textColorHint="@color/register_hint_text_color"
                    android:textCursorDrawable="@null"
                    android:textSize="14sp" />
                <ImageView
                    android:id="@+id/iv_show_psw"
                    android:layout_width="15dp"
                    android:layout_height="48dp"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="8dp"
                    android:src="@drawable/hide_psw_icon" />
            </RelativeLayout>
        </LinearLayout>
    </android.support.v7.widget.CardView>
    <Button
        android:id="@+id/btn_register"
        android:layout_width="fill_parent"
        android:layout_height="35dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginTop="15dp"
        android:background="@drawable/register_btn_selector"
        android:text="注 册"
        android:textColor="@android:color/white"
        android:textSize="18sp" />
</LinearLayout>

(4)自定义ImageViewRoundOval控件。“注册”界面中有一个圆形默认头像,该效果是通过自定义ImageViewRoundOval控件实现的。在view包中创建一个ImageViewRoundOval类并继承ImageView类。

ImageViewRoundOval.java

/**
 * 实现圆形、圆角、椭圆等自定义图片View
 */
public class ImageViewRoundOval extends ImageView {
    private Paint mPaint;
    private int mWidth;
    private int mRadius;                          //圆半径
    private RectF mRect;                          //矩形凹行大小
    private int mRoundRadius;                    //圆角大小
    private BitmapShader mBitmapShader;        //图形渲染
    private Matrix mMatrix;
    private int mType;                              //记录是圆形还是圆角矩形
    public static final int TYPE_CIRCLE = 0;   //圆形
    public static final int TYPE_ROUND = 1;    //圆角矩形
    public static final int TYPE_OVAL = 2;     //椭圆形
    public static final int DEFAUT_ROUND_RADIUS = 10;  //默认圆角大小
    public ImageViewRoundOval(Context context) {
        this(context, null);
    }
    public ImageViewRoundOval(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public ImageViewRoundOval(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }
    private void initView() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mMatrix = new Matrix();
        mRoundRadius = DEFAUT_ROUND_RADIUS;
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //如果是绘制圆形,则强制宽高大小一致
        if (mType == TYPE_CIRCLE) {
            mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
            mRadius = mWidth / 2;
            setMeasuredDimension(mWidth, mWidth);
        }
    }
    @Override
    protected void onDraw(Canvas canvas) {
        if (null == getDrawable()) {
            return;
        }
        setBitmapShader();
        if (mType == TYPE_CIRCLE) {
            canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
        } else if (mType == TYPE_ROUND) {
            mPaint.setColor(Color.RED);
            canvas.drawRoundRect(mRect, mRoundRadius, mRoundRadius, mPaint);
        }else if(mType == TYPE_OVAL){
            canvas.drawOval(mRect, mPaint);
        }
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRect = new RectF(0, 0, getWidth(), getHeight());
    }
    /**
     * 设置BitmapShader
     */
    private void setBitmapShader() {
        Drawable drawable = getDrawable();
        if (null == drawable) {
            return;
        }
        Bitmap bitmap = drawableToBitmap(drawable);
        //将bitmap作为着色器来创建一个BitmapShader
        mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP);
        float scale = 1.0f;
        if (mType == TYPE_CIRCLE) {
            //拿到bitmap宽或高的小值
            int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
            scale = mWidth * 1.0f / bSize;
        } else if (mType == TYPE_ROUND || mType == TYPE_OVAL) {
            //如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,
            //一定要大于view的宽高,所以这里取大值;
            scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f /
                    bitmap.getHeight());
        }
        //shader的变换矩阵,这里主要用于放大或者缩小
        mMatrix.setScale(scale, scale);
        //设置变换矩阵
        mBitmapShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mBitmapShader);
    }
    /**
     * drawable转bitmap
     * @param drawable
     */
    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            return bitmapDrawable.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }
    public int getType() {
        return mType;
    }
    /**
     * 设置图片类型:圆形、圆角矩形、椭圆形
     * @param mType
     */
    public void setType(int mType) {
        if(this.mType != mType){
            this.mType = mType;
            invalidate();
        }
    }
}

(5)修改colors.xml文件。在“注册”界面用到了“注册”界面的背景颜色、注册文本颜色以及“注册”按钮的背景颜色。

    <color name="register_bg_color">#f6f6f6</color>
    <color name="register_hint_text_color">#a3a3a3</color>
    <color name="register_btn_color">#d6d7d7</color>

(6)设置圆角形状。由于“注册”界面输入用户名与密码的控件需要设置圆角形状,因此需要在register_edittext_top_radius.xml文件与register_edittext_bottom_radius.xml文件,分别用于设置控件的顶部与底部的圆角形状。

register_edittext_top_radius.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners
                android:topLeftRadius="4dp"
                android:topRightRadius="4dp" />
        </shape>
    </item>
</layer-list>

register_edittext_bottom_radius.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners
                android:bottomLeftRadius="4dp"
                android:bottomRightRadius="4dp" />
        </shape>
    </item>
</layer-list>

(7)创建背景选择器。在res/drawable文件夹中创建“注册”按钮的背景选择器register_btn_selector.xml。当按钮按下时显示灰色背景,当按钮弹起时显示红色背景。

register_btn_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="4dp" />
            <solid android:color="@color/register_btn_color" />
        </shape>
    </item>
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners android:radius="4dp" />
            <solid android:color="@color/rdTextColorPress" />
        </shape>
    </item>
</selector>

8. MD5加密算法

任务分析:
MD5的全称是Message-Digest Algorithm5(信息-摘要算法),MD5算法简单来说就是把任意长度的字符串变换成固定长度(通常是128位)的十六进制字符串。在存储密码过程中,直接存储明文密码是很危险的,因此在存储密码过程中,直接存储明文密码

任务实施:
(1)创建MD5Utils类(在utils包中创建)。

(2)进行MD5加密。在MD5Utils类中,创建一个md5()方法对密码进行加密。首先通过MessageDigest的getInstanc()方法获取数据加密对象digest,然后通过该对象的digest()方法对密码进行加密。

MD5Utils.java

public class MD5Utils {
    /**
     * md5加密的算法
     */
    public static String md5(String text) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("md5");
            byte[] result = digest.digest(text.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : result) {
                int number = b & 0xff;
                String hex = Integer.toHexString(number);
                if (hex.length() == 1) {
                    sb.append("0" + hex);
                } else {
                    sb.append(hex);
                }
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }
    }
}

9. “注册”界面逻辑代码

任务分析:
在“注册”界面点击“注册”按钮后,需要获取用户名与密码,将用户名和密码(经过MD5加密)保存到SharedPrefereces中。同时,注册成功后需要将用户名传递到“登录”界面(LoginActivity目前还未创建)中。

任务实施:
(1)获取界面控件。在RegisterActivity中创建界面控件的初始化方法init(),用于获取注册界面所要用到的控件以及实现控件的点击事件。

(2)判断SharedPreferences中是否存在需要注册的用户名。在RegisterActivity中创建一个isExistUserName()方法,用于判断SharedPreferences中是否存在需要注册的用户名。

(3)保存注册信息。在RegisterActivity中创建一个saveRegisterInfo()方法,将注册成功的用户名和密码(经过MD5加密)保存到SharedPreferences中。

RegisterActivity.java

public class RegisterActivity extends AppCompatActivity implements View.OnClickListener
{
    private TextView tv_main_title, tv_back;
    private RelativeLayout rl_title_bar;
    private SwipeBackLayout layout;
    private EditText et_psw, et_user_name;
    private ImageView iv_show_psw;
    private Button btn_register;
    private String userName, psw;
    private boolean isShowPsw = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        layout = (SwipeBackLayout) LayoutInflater.from(this).inflate(
                R.layout.base, null);
        layout.attachToActivity(this);
        setContentView(R.layout.activity_register);
        init();
    }
    private void init() {
        tv_main_title = (TextView) findViewById(R.id.tv_main_title);
        tv_main_title.setText("注册");
        rl_title_bar = (RelativeLayout) findViewById(R.id.title_bar);
        rl_title_bar.setBackgroundColor(getResources().getColor(R.color.
                rdTextColorPress));
        tv_back = (TextView) findViewById(R.id.tv_back);
        tv_back.setVisibility(View.VISIBLE);
        btn_register = (Button) findViewById(R.id.btn_register);
        et_user_name = (EditText) findViewById(R.id.et_user_name);
        et_psw = (EditText) findViewById(R.id.et_psw);
        iv_show_psw = (ImageView) findViewById(R.id.iv_show_psw);
        tv_back.setOnClickListener(this);
        iv_show_psw.setOnClickListener(this);
        btn_register.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_back:
                RegisterActivity.this.finish();
                break;
            case R.id.iv_show_psw:
                psw = et_psw.getText().toString();
                if (isShowPsw) {
                    iv_show_psw.setImageResource(R.drawable.hide_psw_icon);
                    et_psw.setTransformationMethod(PasswordTransformationMethod.
                            getInstance());//隐藏密码
                    isShowPsw = false;
                    if (psw != null) {
                        et_psw.setSelection(psw.length());
                    }
                } else {
                    iv_show_psw.setImageResource(R.drawable.show_psw_icon);
                    et_psw.setTransformationMethod(HideReturnsTransformationMethod.
                            getInstance());//显示密码
                    isShowPsw = true;
                    if (psw != null) {
                        et_psw.setSelection(psw.length());
                    }
                }
                break;
            case R.id.btn_register:
                //获取输入在相应控件中的字符串
                userName = et_user_name.getText().toString().trim();
                psw = et_psw.getText().toString().trim();
                if (TextUtils.isEmpty(userName)) {
                    Toast.makeText(RegisterActivity.this, "请输入用户名",
                            Toast.LENGTH_SHORT).show();
                    return;
                } else if (TextUtils.isEmpty(psw)) {
                    Toast.makeText(RegisterActivity.this, "请输入密码",
                            Toast.LENGTH_SHORT).show();
                    return;
                } else if (isExistUserName(userName)) {
                    Toast.makeText(RegisterActivity.this, "此账户名已经存在",
                            Toast.LENGTH_SHORT).show();
                    return;
                } else {
                    Toast.makeText(RegisterActivity.this, "注册成功",
                            Toast.LENGTH_SHORT).show();
                    //把用户名和密码保存到SharedPreferences中
                    saveRegisterInfo(userName, psw);
                    //注册成功后把用户名传递到LoginActivity.java中
                    Intent data = new Intent();
                    data.putExtra("userName", userName);
                    setResult(RESULT_OK, data);
                    RegisterActivity.this.finish();
                }
                break;
        }
    }
    /**
     * 从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有此用户名
     */
    private boolean isExistUserName(String userName) {
        boolean has_userName = false;
        SharedPreferences sp = getSharedPreferences("loginInfo", MODE_PRIVATE);
        String spPsw = sp.getString(userName, "");
        if (!TextUtils.isEmpty(spPsw)) {
            has_userName = true;
        }
        return has_userName;
    }
    /**
     * 保存用户名和密码到SharedPreferences中
     */
    private void saveRegisterInfo(String userName, String psw) {
        String md5Psw = MD5Utils.md5(psw);           //把密码用MD5加密
        //loginInfo表示文件名
        SharedPreferences sp = getSharedPreferences("loginInfo", MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();//获取编辑器
        //以用户名为key,密码为value保存到SharedPreferences中
        editor.putString(userName, md5Psw);
        editor.commit();//提交修改
    }
}

(4)修改清单文件。由于注册界面向右滑动会关闭该界面,因此需要给界面添加透明主题的样式,在清单文件的RegisterActivity对应的activity标签中添加如下代码:

android:theme="@style/AppTheme.TransparentActivity"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值