17. “我”模块(一)之个人资料

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

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

知识点

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

个人资料

任务综述:
“个人资料”界面主要用于显示用户信息,其中包含用户头像、用户名、昵称、性别和签名,除了用户名无须修改以外,其余信息均可修改。当注册一个新用户并第一次进入“个人资料”界面时,除用户名以外的信息均使用默认值,当修改个人资料信息时需要使用SQLite数据库进行保存。

7. “个人资料”界面

任务分析:
"个人资料"界面主要用于展示用户的个人信息,包括用户头像、用户名、昵称、性别和签名,界面如图所示。

10186693-ff96001e6a66e23b.png
“个人资料”界面

任务实施:
(1)创建“个人资料”界面:UserInfoActivity&activity_user_info。在该布局文件中,通过<include>标签将main_title_bar.xml(标题栏)引入。

(2)放置界面控件。
1个ImageViewRoundOval控件显示头像;
5个TextView控件显示每行标题(头像、用户名、昵称、性别、签名);
4个TextView控件显示对应的属性值;
5个View控件显示5条灰色分隔线。

activity_user_info

<?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="@android:color/white"
    android:orientation="vertical">
    <include layout="@layout/main_title_bar" />
    <RelativeLayout
        android:id="@+id/rl_head"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="头    像"
            android:textColor="#000000"
            android:textSize="16sp" />
        <com.itheima.topline.view.ImageViewRoundOval
            android:id="@+id/iv_head_icon"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:scaleType="fitXY"
            android:src="@drawable/default_head" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="#E4E4E4" />
    <RelativeLayout
        android:id="@+id/rl_account"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="用户名"
            android:textColor="#000000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dp"
            android:textColor="#a3a3a3"
            android:textSize="14sp" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="#E4E4E4" />
    <RelativeLayout
        android:id="@+id/rl_nickName"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="昵    称"
            android:textColor="#000000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_nickName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dp"
            android:singleLine="true"
            android:textColor="#a3a3a3"
            android:textSize="14sp" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="#E4E4E4" />
    <RelativeLayout
        android:id="@+id/rl_sex"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:text="性    别"
            android:textColor="#000000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_sex"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dp"
            android:textColor="#a3a3a3"
            android:textSize="14sp" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="#E4E4E4" />
    <RelativeLayout
        android:id="@+id/rl_signature"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:singleLine="true"
            android:text="签    名"
            android:textColor="#000000"
            android:textSize="16sp" />
        <TextView
            android:id="@+id/tv_signature"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="5dp"
            android:textColor="#a3a3a3"
            android:textSize="14sp" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:background="#E4E4E4" />
</LinearLayout>

(3)放置dialog_select_photo.xml文件中的控件。由于点击“个人资料”界面中的头像条目时会弹出一个对话框,对话框中有“从相册中选取”与“拍照”两个按钮,因此需要在res/layout文件夹中创建一个dialog_select_photo.xml文件,在该文件中放置两个TextView控件,分别用于显示“从相册中选取”与“拍照”文本;一个View控件用于显示灰色分隔线。

dialog_select_photo.xml

<?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="@android:color/white"
    android:gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_select_gallery"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="从相册中选取"
        android:textColor="@android:color/black"
        android:textSize="14sp" />
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/divider_line_color" />
    <TextView
        android:id="@+id/tv_select_camera"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="拍照"
        android:textColor="@android:color/black"
        android:textSize="14sp" />
</LinearLayout>

“个人资料”界面逻辑代码

任务分析:
“个人资料”界面主要用于展示用户的相关信息,当进入“个人资料”界面时,首先查询数据库中的用户信息,并将信息展示到界面中。“个人资料”界面中的昵称、性别和签名是可以修改的,因此需要添加相应的监听事件,当点击“昵称”时跳转到“昵称修改”界面,当点击“性别”时弹出“性别选择”对话框,当点击“签名”时跳转“签名修改”界面。

任务实施:
(1)获取界面控件。在UserInfoActivity中创建界面控件的初始化方法init(),获取“个人资料”界面所要用到的控件。

(2)设置点击事件。由于界面中除了用户和头像以外的其余属性值都可以修改,因此需要为其他属性所在的条目设置点击事件。在UserInfoActivity类中实现OnClickListener接口中的onClick()方法。

(3)为界面控件设置值。创建一个initData()方法用于从数据库中获取数据,如果数据库中的数据为空,则为此账号设置默认的属性值并保存到数据库中。

UserInfoActivity

public class UserInfoActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView tv_main_title,tv_back;
    private SwipeBackLayout layout;
    private TextView tv_nickName, tv_signature, tv_user_name, tv_sex;
    private RelativeLayout rl_nickName, rl_sex, rl_signature,rl_head, rl_title_bar;
    private String spUserName;
    private static final int CHANGE_NICKNAME = 1;   //修改昵称的自定义常量
    private static final int CHANGE_SIGNATURE = 2; //修改签名的自定义常量
    private static final int CROP_PHOTO1 = 3;       //裁剪图片
    private static final int CROP_PHOTO2 = 4;       //裁剪本地图片
    private static final int SAVE_PHOTO = 5;        //修改签名的自定义常量
    private ImageViewRoundOval iv_photo;
    private Bitmap head;                                //头像Bitmap
    private static String path = "/sdcard/TopLine/myHead/"; //sd路径
    @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_user_info);
        //从SharedPreferences中获取登录时的用户名
        spUserName = UtilsHelper.readLoginUserName(this);
        init();
        initData();
        setListener();
    }
    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);
        rl_nickName = (RelativeLayout) findViewById(R.id.rl_nickName);
        rl_sex = (RelativeLayout) findViewById(R.id.rl_sex);
        rl_signature = (RelativeLayout) findViewById(R.id.rl_signature);
        tv_nickName = (TextView) findViewById(R.id.tv_nickName);
        tv_user_name = (TextView) findViewById(R.id.tv_user_name);
        tv_sex = (TextView) findViewById(R.id.tv_sex);
        tv_signature = (TextView) findViewById(R.id.tv_signature);
        rl_head= (RelativeLayout) findViewById(R.id.rl_head);
        iv_photo = (ImageViewRoundOval) findViewById(R.id.iv_head_icon);
    }
    /**
     * 获取数据
     */
    private void initData() {
        UserBean bean = null;
        bean = DBUtils.getInstance(this).getUserInfo(spUserName);
        //首先判断一下数据库是否有数据
        if (bean == null) {
            bean = new UserBean();
            bean.setUserName(spUserName);
            bean.setNickName("问答精灵");
            bean.setSex("男");
            bean.setSignature("传智播客问答精灵");
            iv_photo.setImageResource(R.drawable.default_head);
            //保存用户信息到数据库
            DBUtils.getInstance(this).saveUserInfo(bean);
        }
        setValue(bean);
    }
    /**
     * 为界面控件设置值
     */
    private void setValue(UserBean bean) {
        tv_nickName.setText(bean.getNickName());
        tv_user_name.setText(bean.getUserName());
        tv_sex.setText(bean.getSex());
        tv_signature.setText(bean.getSignature());
        Bitmap bt = BitmapFactory.decodeFile(bean.getHead()); //从SD卡中找头像,转换成Bitmap
        if (bt != null) {
            @SuppressWarnings("deprecation")
            Drawable drawable = new BitmapDrawable(bt);      //转换成drawable
            iv_photo.setImageDrawable(drawable);
        } else {
            iv_photo.setImageResource(R.drawable.default_head);
        }
    }
    /**
     * 设置控件的点击监听事件
     */
    private void setListener() {
        tv_back.setOnClickListener(this);
        rl_nickName.setOnClickListener(this);
        rl_sex.setOnClickListener(this);
        rl_signature.setOnClickListener(this);
        rl_head.setOnClickListener(this);
    }
    /**
     * 控件的点击事件
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_back:      //返回键的点击事件
                this.finish();
                break;
            case R.id.rl_nickName: //昵称的点击事件
                String name = tv_nickName.getText().toString(); //获取昵称控件上的数据
                Bundle bdName = new Bundle();
                bdName.putString("content", name);                //传递界面上的昵称数据
                bdName.putString("title", "昵称");
                bdName.putInt("flag", 1);                           //flag传递1时表示是修改昵称
                //跳转到个人资料修改界面
                enterActivityForResult(ChangeUserInfoActivity.class,CHANGE_NICKNAME, bdName);
                break;
            case R.id.rl_sex:       //性别的点击事件
                String sex = tv_sex.getText().toString(); //获取性别控件上的数据
                sexDialog(sex);
                break;
            case R.id.rl_signature:  //签名的点击事件
                String signature = tv_signature.getText().toString(); //获取签名控件上的数据
                Bundle bdSignature = new Bundle();
                bdSignature.putString("content", signature);            //传递界面上的签名数据
                bdSignature.putString("title", "签名");
                bdSignature.putInt("flag", 2);                            //flag传递2时表示是修改签名
                //跳转到个人资料修改界面
                enterActivityForResult(ChangeUserInfoActivity.class,CHANGE_SIGNATURE, bdSignature);
                break;
            case R.id.rl_head:       //头像的点击事件
                showTypeDialog();
                break;
            default:
                break;
        }
    }
    private void showTypeDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        final AlertDialog dialog = builder.create();
        View view = View.inflate(this, R.layout.dialog_select_photo, null);
        TextView tv_select_gallery = (TextView) view.findViewById(
                R.id.tv_select_gallery);
        TextView tv_select_camera = (TextView) view.findViewById(R.id.tv_select_camera);
        tv_select_gallery.setOnClickListener(new View.OnClickListener() { //在相册中选取
            @Override
            public void onClick(View v) {
                Intent intent1 = new Intent(Intent.ACTION_PICK, null);
                intent1.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        "image/*");
                startActivityForResult(intent1, 3);
                dialog.dismiss();
            }
        });
        tv_select_camera.setOnClickListener(new View.OnClickListener() { //调用照相机
            @Override
            public void onClick(View v) {
                Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent2.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(Environment.getExternalStorageDirectory(),
                                spUserName+"_head.jpg")));
                startActivityForResult(intent2, 4); //采用ForResult打开
                dialog.dismiss();
            }
        });
        dialog.setView(view);
        dialog.show();
    }
    /**
     * 设置性别的弹出框
     */
    private void sexDialog(String sex){
        int sexFlag=0;
        if("男".equals(sex)){
            sexFlag=0;
        }else if("女".equals(sex)){
            sexFlag=1;
        }
        final String items[]={"男","女"};
        AlertDialog.Builder builder=new AlertDialog.Builder(this);//先得到构造器
        builder.setTitle("性别"); //设置标题
        builder.setSingleChoiceItems(items,sexFlag,new DialogInterface
                .OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                //第二个参数which是默认选中的哪个项
                Toast.makeText(UserInfoActivity.this,items[which],
                        Toast.LENGTH_SHORT).show();
                setSex(items[which]);
            }
        });
        builder.create().show();
    }
    /**
     * 更新界面上的性别数据
     */
    private void setSex(String sex){
        tv_sex.setText(sex);
        //更新数据库中的性别字段
        DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("sex",sex,
                spUserName);
    }
    /**
     * 获取回传数据时需使用的跳转方法,第一个参数to表示需要跳转到的界面,
     * 第二个参数requestCode表示一个请求码,第三个参数b表示跳转时传递的数据
     */
    public void enterActivityForResult(Class<?> to, int requestCode, Bundle b) {
        Intent i = new Intent(this, to);
        i.putExtras(b);
        startActivityForResult(i, requestCode);
    }
    /**
     * 回传数据
     */
    private String new_info; //最新数据
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CROP_PHOTO1:
                if (resultCode == RESULT_OK) {
                    cropPhoto(data.getData()); //裁剪图片
                }
                break;
            case CROP_PHOTO2:
                if (resultCode == RESULT_OK) {
                    File temp = new File(Environment.getExternalStorageDirectory() +"/"+
                            spUserName+"_head.jpg");
                    cropPhoto(Uri.fromFile(temp)); //裁剪图片
                }
                break;
            case SAVE_PHOTO:
                if (data != null) {
                    Bundle extras = data.getExtras();
                    head = extras.getParcelable("data");
                    if (head != null) {
                        String fileName=setPicToView(head); //保存在SD卡中
                        //保存头像地址到数据库中
                        DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("head",
                                fileName,spUserName);
                        iv_photo.setImageBitmap(head); //用ImageView显示出来
                        //发送广播更新“我”的界面中的头像
                        Intent intent = new Intent(
                                UpdateUserInfoReceiver.ACTION.UPDATE_USERINFO);
                        intent.putExtra(
                                UpdateUserInfoReceiver.INTENT_TYPE.TYPE_NAME,
                                UpdateUserInfoReceiver.INTENT_TYPE.UPDATE_HEAD);
                        intent.putExtra("head", fileName);
                        sendBroadcast(intent);
                    }
                }
                break;
            case CHANGE_NICKNAME:  //个人资料修改界面回传过来的昵称数据
                if (data != null) {
                    new_info = data.getStringExtra("nickName");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_nickName.setText(new_info);
                    //更新数据库中的昵称字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
                            "nickName", new_info, spUserName);
                }
                break;
            case CHANGE_SIGNATURE: //个人资料修改界面回传过来的签名数据
                if (data != null) {
                    new_info = data.getStringExtra("signature");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_signature.setText(new_info);
                    //更新数据库中的签名字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
                            "signature", new_info, spUserName);
                }
                break;
        }
    }
    /**
     * 调用系统的裁剪功能
     */
    public void cropPhoto(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        //aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        //outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, SAVE_PHOTO);
    }
    private String setPicToView(Bitmap mBitmap) {
        String sdStatus = Environment.getExternalStorageState();
        if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { //检测sd是否可用
            return "";
        }
        FileOutputStream b = null;
        File file = new File(path);
        file.mkdirs(); //创建文件夹
        String fileName = path + spUserName+"_head.jpg"; //图片名字
        try {
            b = new FileOutputStream(fileName);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b); //把数据写入文件
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                b.flush();
                b.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileName;
    }
}

(4)修改DBUtils.java文件。由于“个人资料”界面需要获取、保存以及修改个人资料信息,因此需要在utils包中找到DBUtils类。

/**
     * 保存个人资料信息
     */
    public void saveUserInfo(UserBean bean) {
        ContentValues cv = new ContentValues();
        cv.put("userName", bean.getUserName());
        cv.put("nickName", bean.getNickName());
        cv.put("sex", bean.getSex());
        cv.put("signature", bean.getSignature());
        db.insert(SQLiteHelper.U_USERINFO, null, cv);
    }
    /**
     * 获取个人资料信息
     */
    public UserBean getUserInfo(String userName) {
        String sql = "SELECT * FROM " + SQLiteHelper.U_USERINFO + " WHERE userName=?";
        Cursor cursor = db.rawQuery(sql, new String[]{userName});
        UserBean bean = null;
        while (cursor.moveToNext()) {
            bean = new UserBean();
            bean.setUserName(cursor.getString(cursor.getColumnIndex("userName")));
            bean.setNickName(cursor.getString(cursor.getColumnIndex("nickName")));
            bean.setSex(cursor.getString(cursor.getColumnIndex("sex")));
            bean.setSignature(cursor.getString(cursor.getColumnIndex("signature")));
            bean.setHead(cursor.getString(cursor.getColumnIndex("head")));
        }
        cursor.close();
        return bean;
    }
    /**
     * 修改个人资料
     */
    public void updateUserInfo(String key, String value, String userName) {
        ContentValues cv = new ContentValues();
        cv.put(key, value);
        db.update(SQLiteHelper.U_USERINFO, cv, "userName=?",new String[]{userName});
    }

(5)修改清单文件。“个人资料”界面向右滑动会关闭界面,因此需要给该界面添加透明主题的样式。

<activity
     android:name=".activity.UserInfoActivity"
     android:theme="@style/AppTheme.TransparentActivity" />

(6)修改MeFragment.java文件。当用户处于登录状态时,点击“我”界面中的头像会跳转到“个人资料”界面,因此需要找到onClick()方法,在该方法的注释“//跳转到“个人资料”界面”下方添加如下代码:

 //跳转到个人资料界面
Intent userinfo = new Intent(getActivity(), UserInfoActivity.class);
startActivity(userinfo);

(7)添加权限。在“个人资料”界面修改头像时会访问SD卡,因此需要在清单文件中添加SD卡的写权限。

<!--SD卡的写权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值