实训第六周(2)

接下来完成MeFragment中可选择进入的AccountInfoActivity(账号信息详情页),可修改个人信息

1. activity_account_info.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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:fitsSystemWindows="true">

    <include layout="@layout/title_layout"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@color/interval_color">

        <View
            android:layout_width="match_parent"
            android:layout_height="10dp"/>

        <RelativeLayout
            android:id="@+id/layout_head"
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="80dp">

            <TextView
                android:text="@string/account_head_picture"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <com.joooonho.SelectableRoundedImageView
                android:id="@+id/iv_head_picture"
                android:layout_alignParentRight="true"
                android:layout_marginTop="5dp"
                android:layout_marginBottom="5dp"
                android:layout_width="70dp"
                android:scaleType="fitXY"
                app:sriv_oval="true"
                android:src="@mipmap/app_logo_main"
                android:layout_height="70dp"/>
        </RelativeLayout>
        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="40dp">

            <TextView
                android:id="@+id/tv_1"
                android:text="账号"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <TextView
                android:layout_toRightOf="@+id/tv_1"
                android:layout_marginLeft="10dp"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/tv_account"
                android:gravity="center_vertical|right"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </RelativeLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="40dp">
            <TextView
                android:id="@+id/tv_2"
                android:text="@string/account_nick"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <EditText
                android:layout_toRightOf="@+id/tv_2"
                android:layout_marginLeft="10dp"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/et_account_nick"
                android:gravity="center_vertical|right"
                android:layout_width="match_parent"
                android:background="@null"
                android:layout_height="match_parent"/>
        </RelativeLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="40dp">
            <TextView
                android:id="@+id/tv_3"
                android:text="@string/account_sex"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <TextView
                android:layout_toRightOf="@+id/tv_3"
                android:layout_marginLeft="10dp"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/tv_account_sex"
                android:gravity="center_vertical|right"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </RelativeLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="40dp">

            <TextView
                android:id="@+id/tv_4"
                android:text="@string/account_birth"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <TextView
                android:layout_toRightOf="@+id/tv_4"
                android:layout_marginLeft="10dp"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/tv_account_birth"
                android:gravity="center_vertical|right"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </RelativeLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="40dp">
            <TextView
                android:id="@+id/tv_5"
                android:text="@string/account_location"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <TextView
                android:layout_toRightOf="@+id/tv_5"
                android:layout_marginLeft="10dp"
                android:gravity="center_vertical|right"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/tv_account_location"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </RelativeLayout>
        <View
            android:layout_width="match_parent"
            android:layout_height="0.8dp"/>

        <RelativeLayout
            android:background="@color/white_color"
            android:layout_width="match_parent"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:layout_height="60dp">

            <TextView
                android:id="@+id/tv_6"
                android:text="@string/account_signature"
                android:gravity="center_vertical"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textSize="16sp"
                android:textColor="@color/app_black_color"/>

            <EditText
                android:hint="@string/signature_hint"
                android:layout_toRightOf="@+id/tv_6"
                android:layout_marginLeft="10dp"
                android:textSize="16sp"
                android:textColor="@color/default_text_color"
                android:id="@+id/et_account_signature"
                android:gravity="center_vertical|right"
                android:maxLines="2"
                android:background="@null"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </RelativeLayout>
    </LinearLayout>

</LinearLayout>


2. 显示数据

通过NimUserHandler获得本地账户,由在本地账户中设置的属性数据设置个人信息页并显示

    private void showData() {
        mAccountBean = NimUserHandler.getInstance().getLocalAccount();
        if (mAccountBean != null) {
            ImageUtils.setImageByFile(this, mIvHead,
                    mAccountBean.getHeadImgUrl(), R.mipmap.bg_img_defalut);
            mTvAccount.setText(mAccountBean.getAccount());
            mEtNick.setText(mAccountBean.getNick());
            if (mAccountBean.getGenderEnum() == GenderEnum.FEMALE) {
                mTvSex.setText("女");
            } else if (mAccountBean.getGenderEnum() == GenderEnum.MALE) {
                mTvSex.setText("男");
            } else {
                mTvSex.setText("保密");
            }
            mEtSignature.setText(mAccountBean.getSignature());
            String birthday = mAccountBean.getBirthDay();
            if (TextUtils.isEmpty(birthday)) {
                mTvBirthDay.setText("未设置");
            } else {
                mTvBirthDay.setText(birthday);
            }
            String location = mAccountBean.getLocation();
            if (TextUtils.isEmpty(location)) {
                mTvLocation.setText("未设置");
            } else {
                mTvLocation.setText(location);
            }
        }
    }


3. 初始化

mInputMethodManager用于控制显示或隐藏输入法面板

然后在可以为设置头像,性别,生日,地区,编辑状态,回退这些控件上添加OnClickListener

为编辑昵称和签名的控件上添加OnTouchListener

private void init() {
        mInputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        // 文字
        mLayoutHead.setOnClickListener(this);
        mTvSex.setOnClickListener(this);
        mTvBirthDay.setOnClickListener(this);
        mTvLocation.setOnClickListener(this);

        // 标题栏
        mIvBack.setOnClickListener(this);
        mIvMenu.setOnClickListener(this);

        // 输入框
        mEtNick.setOnTouchListener(this);
        mEtSignature.setOnTouchListener(this);

        // 结束编辑,相当于初始化为非编辑状态
        finishEdit();
    }

4. onClick 

设置点击到不同控件时,可以设置对应的不同属性

@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.layout_head:
                setHeadImg();
                break;
            case R.id.tv_account_sex:
                setSex();
                break;
            case R.id.tv_account_location:
                setLocation();
                break;
            case R.id.tv_account_birth:
                setBirthday();
                break;
            case R.id.iv_back_btn:
                this.finish();
                break;
            case R.id.iv_menu_btn:
                if (isEditor) {
                    finishEdit();
                } else {
                    startEdit();
                }
                break;
        }
    }


5. onTouch——用于设置要自行输入的几项属性(昵称,签名)

如果是要设置昵称和签名时,获取焦点并将光标移动到末尾

显示软键盘

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isEditor) {
            if (v.getId() == R.id.et_account_nick) {
                mEtNick.requestFocus();
                mEtNick.setSelection(mEtNick.getText().length());
                mInputMethodManager.showSoftInput(mEtNick, 0);
            } else if (v.getId() == R.id.et_account_signature) {
                mEtSignature.requestFocus();
                mEtSignature.setSelection(mEtSignature.getText().length());
                mInputMethodManager.showSoftInput(mEtSignature, 0);
            }
            return true;
        }
        return false;
    }


6. 启动编辑

当右上方菜单栏为此图标时,处在编辑状态(即点击该图标,可进入结束编辑状态)

所有控件处于可点击(头像,性别,地区,生日)或可编辑(昵称,签名)状态

    private void startEdit() {
        mIvMenu.setImageResource(R.mipmap.done);
        // 可点击
        mLayoutHead.setClickable(true);
        mTvSex.setClickable(true);
        mTvLocation.setClickable(true);
        mTvBirthDay.setClickable(true);
        // 可编辑
        mEtNick.setFocusable(true);
        mEtNick.setFocusableInTouchMode(true);
        mEtSignature.setFocusable(true);
        mEtSignature.setFocusableInTouchMode(true);

        isEditor = true;
    }


7. 结束编辑

判断是否有修改

若有修改,通过NimUserHandler的setLocalAccount方法将数据更新到缓存,syncChange2Servive方法将数据更新到服务器

结束编辑后,右上方菜单栏图标变换为(即点击该图标,可重新进入编辑状态)

并将控件设置为不可点击(头像,性别,地区,生日),不可编辑(昵称,签名)状态

   private void finishEdit() {
        if (!mEtNick.getText().toString()
                .equals(mAccountBean.getNick())) {
            mAccountBean.setNick(mEtNick.getText().toString());
            haveAccountChange = true;
        }

        if (!mEtSignature.getText().toString()
                .equals(mAccountBean.getSignature())) {
            mAccountBean.setSignature(mEtSignature.getText().toString());
            haveAccountChange = true;
        }

        if (haveAccountChange) {

            // 将数据更新到缓存
            NimUserHandler.getInstance().setLocalAccount(mAccountBean);
            // 通知handler将数据更新到服务器
            NimUserHandler.getInstance().syncChange2Service();

            haveAccountChange = false;
        }

        mIvMenu.setImageResource(R.mipmap.editor);
        // 不可点击
        mLayoutHead.setClickable(false);
        mTvSex.setClickable(false);
        mTvLocation.setClickable(false);
        mTvBirthDay.setClickable(false);
        // 不可编辑
        mEtNick.setFocusable(false);
        mEtNick.setFocusableInTouchMode(false);
        mEtSignature.setFocusable(false);
        mEtSignature.setFocusableInTouchMode(false);

        isEditor = false;
    }


8. 设置性别

利用AlertDialog

    private void setSex(){
        final int[] selected = new int[1];
        if (mAccountBean.getGenderEnum() == GenderEnum.MALE) {
            selected[0] = 0;
        } else if (mAccountBean.getGenderEnum() == GenderEnum.FEMALE) {
            selected[0] = 1;
        } else {
            selected[0] = 2;
        }
        final String[] items = new String[]{"男", "女", "保密"};
        new AlertDialog.Builder(this)
                .setTitle("性别")
                .setSingleChoiceItems(items, selected[0], new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (which != selected[0]) {
                            if (which == 0) {
                                mAccountBean.setGenderEnum(GenderEnum.MALE);
                                mTvSex.setText("男");
                            } else if (which == 1) {
                                mAccountBean.setGenderEnum(GenderEnum.FEMALE);
                                mTvSex.setText("女");
                            } else {
                                mAccountBean.setGenderEnum(GenderEnum.UNKNOWN);
                                mTvSex.setText("保密");
                            }
                            haveAccountChange = true;
                        }
                        dialog.dismiss();
                    }
                }).create().show();
    }


9. 设置头像,拍照或选择照片

用LayoutInflater找到dialog_set_head_img.xml布局文件,并实例化

dialog_set_head_img.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white_color"
    android:id="@+id/layout_dialog">

    <TextView
        android:id="@+id/tv_take_photo"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:text="@string/dialog_take_photo"
        android:textColor="@color/app_black_color"
        android:textSize="18sp"
        android:gravity="center"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/interval_color"/>

    <TextView
        android:id="@+id/tv_select_img"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:text="@string/dialog_select_photo"
        android:textColor="@color/app_black_color"
        android:textSize="18sp"
        android:gravity="center"/>
</LinearLayout>

(1)为“拍照”控件添加OnClickListener

使用MediaStore.ACTION_IMAGE_CAPTURE打开照相机

设置图片路径,创建图片文件并保存

若出错,显示“启动相机出错!请重试”

(2)为“从相册中选择”控件添加OnClickListener

查询外置内存卡(EXTERNAL_CONTENT_URI)

选择类型为图片

private void setHeadImg() {
        View view = LayoutInflater.from(this).inflate(R.layout.dialog_set_head_img, null);
        final AlertDialog alertDialog = new AlertDialog.Builder(this).setView(view).create();
        TextView take = (TextView) view.findViewById(R.id.tv_take_photo);
        TextView select = (TextView) view.findViewById(R.id.tv_select_img);
        take.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
                try {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    mHeadImgPath = Constant.APP_CACHE_PATH + File.separator + "image"
                            + File.separator + mAccountBean.getAccount() + ".jpg";
                    Uri uri = Uri.fromFile(new File(mHeadImgPath));
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);//设置图像文件名
                    startActivityForResult(intent, TAKE_PHOTO);
                } catch (Exception e) {
                    ToastUtils.showMessage(AccountInfoActivity.this, "启动相机出错!请重试");
                    e.printStackTrace();
                }

            }
        });
        select.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                alertDialog.dismiss();
                Intent intent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(Intent.createChooser(intent, "选择头像图片"), SELECT_PHOTO);
            }
        });
        alertDialog.show();
    }


10. 处理拍照回传数据

获取图片旋转角度

从图像路径获取bitmap,并根据给定的显示宽高对bitmap进行压缩(600x400)

根据给定的角度(bitmapDegree),对bitmap进行旋转

将bitmap保存到本地

显示,记录更新,同步至网易云服务器

    private void dealTakePhotoResult() {
        Flowable.just(mHeadImgPath)
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String path) throws Exception {
                        // 调整旋转角度,压缩
                        int bitmapDegree = ImageUtils.getBitmapDegree(mHeadImgPath);
                        Bitmap bitmap = ImageUtils.getBitmapFromFile(mHeadImgPath, 600, 400);
                        bitmap = ImageUtils.rotateBitmapByDegree(bitmap, bitmapDegree);
                        ImageUtils.saveBitmap2Jpg(bitmap, path);
                        return bitmap;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bitmap) throws Exception {
                        // 显示,记录更新,同步至网易云服务器
                        if (bitmap != null) {
                            // 上传至服务器
                            uploadHeadImg(bitmap);
                        }
                    }
                });
    }


11. 得到回传数据

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            if (requestCode == TAKE_PHOTO) {
                dealTakePhotoResult();
            } else if (requestCode == SELECT_PHOTO) {
                mHeadImgPath = ImageUtils.getFilePathFromUri(AccountInfoActivity.this, data.getData());
                dealTakePhotoResult();
            }
        }
    }


12. 将头像数据上传至网易云服务器存储,获取服务器返回URL

通过NimClient的getService接口获取到NosService(网易云存储服务)服务实例,调用upload方法上传到网易云服务器存储图像

    private void uploadHeadImg(final Bitmap bitmap) {
        AbortableFuture<String> upload = NIMClient.getService(NosService.class)
                .upload(new File(mHeadImgPath), "image/ipeg");
        upload.setCallback(new RequestCallback() {
            @Override
            public void onSuccess(Object param) {
                Log.e(TAG,"uploadHeadImg onSuccess url = " + param.toString());
                mIvHead.setImageBitmap(bitmap);
                // 保存图片本地路径和服务器路径
                mAccountBean.setHeadImgUrl(param.toString());
                haveAccountChange = true;
            }

            @Override
            public void onFailed(int code) {
                Log.e(TAG,"uploadHeadImg onFailed code " + code);
                ToastUtils.showMessage(AccountInfoActivity.this,
                        "修改失败,头像上传失败,code:" + code);
            }

            @Override
            public void onException(Throwable exception) {
                Log.e(TAG,"uploadHeadImg onException message " + exception.getMessage());
                ToastUtils.showMessage(AccountInfoActivity.this,
                        "修改失败,图像上传出错:" + exception.getMessage());
            }
        });
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值