商城項(xiàng)目實(shí)戰(zhàn) | 22.1 CircleImageView 實(shí)現(xiàn)我的模塊

本文為菜鳥窩作者劉婷的連載。”商城項(xiàng)目實(shí)戰(zhàn)”系列來聊聊仿”京東淘寶的購(gòu)物商城”如何實(shí)現(xiàn)。

商城項(xiàng)目中有主要的5大模塊,分別為主頁(yè)模塊、熱門模塊、分類模塊、購(gòu)物車模塊以及我的模塊,其中我的模塊的主要功能是顯示用戶信息,里面包含了用戶頭像、我的訂單、我的收藏、收貨地址以及我的消息等,如下圖所示。

效果圖
效果圖

因?yàn)楝F(xiàn)在很多的賬號(hào)頭像都是圓形頭像,而且圓形頭像也更為的美觀些,所以本項(xiàng)目中我的頭像也是圓形頭像,那么這個(gè)圓形頭像是如何實(shí)現(xiàn)的呢?另外我的頭像下面還有個(gè)“點(diǎn)擊登錄”的文本,也就是還有登錄后的顯示效果嗎?帶著疑問往下看。

實(shí)現(xiàn)圓形頭像

實(shí)現(xiàn)用戶頭像為圓形頭像需要借助于第三方的開源控件 CircleImageView,這是一款 Android 開源顯示圓形圖像的控件,目前已經(jīng)開源到了 GitHub 上面,具體的源代碼可以進(jìn)入 Github 源碼查看。

1. CircleImageView 的相關(guān)屬性

CircleImageView 作為自定義的開源控件,主要有四大自定義的屬性,分別如下。

<declare-styleable name="CircleImageView">
        <attr name="civ_border_width" format="dimension" />
        <attr name="civ_border_color" format="color" />
        <attr name="civ_border_overlay" format="boolean" />
        <attr name="civ_fill_color" format="color" />
    </declare-styleable>

其中 civ_border_width 是設(shè)置圖像外部邊框?qū)挾龋琧iv_border_color 表示圖像外部邊框顏色,civ_border_overlay 是一個(gè) boolean 值, false 代表邊框是繪制在圖片外部,不覆蓋圖片最外層,true 則是在圖片之上繪制,覆蓋最外層,civ_fill_color 默認(rèn)為透明,表示圖像填充的顏色。

2. CircleImageView 的使用方法

CircleImageView 的使用方法很簡(jiǎn)單,而且該控件在目前主流的 Android 設(shè)備上面的顯示效果都很不錯(cuò),和之前使用第三方框架一樣的,首先要集成 CircleImageView。

2.1 Gradle 添加 CircleImageView 依賴

集成 CircleImageView 就是要在 module 的 build.gradle 文件中添加對(duì) CircleImageView 的依賴。

dependencies {
    ......
    compile 'de.hdodenhof:circleimageview:2.1.0'

}

添加好了依賴,就可以開始使用 CircleImageView 開源控件了。

2.2 布局中添加 CircleImageView

CircleImageView 作為一款開源控件,和其他的 Android 控件的使用方法一樣,直接在布局文件 layout 文件中添加該控件。

<de.hdodenhof.circleimageview.CircleImageView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/profile_image"
    android:layout_width="96dp"
    android:layout_height="96dp"
    android:src="@drawable/profile"
    app:civ_border_width="2dp"
    app:civ_border_color="#FF000000"/>

將 CircleImageView 添加到布局文件中,同時(shí)對(duì)控件的相應(yīng)屬性進(jìn)行設(shè)置,布局中添加好了 CircleImageView 控件后,將布局在 Activity/Fragment 中加載即可。

實(shí)現(xiàn)我的模塊

我的模塊的布局比較簡(jiǎn)單,同樣的功能也不復(fù)雜,結(jié)合上文介紹的 CircleImageView 來實(shí)現(xiàn)我的模塊。

1. 設(shè)計(jì)我的模塊布局

根據(jù)上文效果圖中可以看出,布局中需要有個(gè)顯示圖片的 ImageView以及下面4個(gè)列表,布局最好是簡(jiǎn)單化比較好,所以在這里下面的4個(gè)列表就直接使用 TextView 實(shí)現(xiàn)就好。

<?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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bg_color">

    <FrameLayout
        android:id="@+id/mine_layout_head"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="?attr/colorPrimary" >

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/mine_img_head"
            android:layout_width="@dimen/mine_img_head_width"
            android:layout_height="@dimen/mine_img_head_width"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="12dp"
            app:civ_border_width="2dp"
            app:civ_border_color="#FFFFFF"
            android:src="@mipmap/default_head">

        </de.hdodenhof.circleimageview.CircleImageView>

        <TextView
            android:id="@+id/mine_tv_username"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="60dp"
            android:layout_marginBottom="9dp"
            android:gravity="center"
            android:text="@string/to_login"
            android:textColor="@color/white"
            android:textSize="16sp" />

    </FrameLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="@dimen/mine_list_info_margin_top"
            android:orientation="vertical">

            <TextView
                android:id="@+id/mine_tv_my_orders"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/largePadding"
                android:background="@drawable/selector_list_item"
                android:drawableLeft="@mipmap/icon_list_order"
                android:gravity="center_vertical"
                android:drawablePadding="20dp"
                android:text="@string/my_orders"
                android:textColor="@color/black"/>

            <View style="@style/line_vertical"/>

            <TextView
                android:id="@+id/mine_tv_favorite"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/largePadding"
                android:background="@drawable/selector_list_item"
                android:drawableLeft="@mipmap/icon_favorite"
                android:gravity="center_vertical"
                android:drawablePadding="20dp"
                android:text="@string/my_favorite"
                android:textColor="@color/black"/>

            <View style="@style/line_vertical"/>

            <TextView
                android:id="@+id/mine_tv_address"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/largePadding"
                android:background="@drawable/selector_list_item"
                android:drawableLeft="@mipmap/icon_location"
                android:gravity="center_vertical"
                android:drawablePadding="20dp"
                android:text="@string/my_addresses"
                android:textColor="@color/black"/>

            <View style="@style/line_vertical"/>

            <TextView
                android:id="@+id/mine_tv_notification"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/largePadding"
                android:background="@drawable/selector_list_item"
                android:drawableLeft="@mipmap/icon_msg"
                android:gravity="center_vertical"
                android:drawablePadding="20dp"
                android:text="@string/my_msg"
                android:textColor="@color/black"/>

            <Button
                android:id="@+id/mine_btn_logout"
                android:text="@string/logout"
                style="@style/bigRedButton"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="20dp"
                android:layout_marginBottom="20dp"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                />

        </LinearLayout>

    </ScrollView>
</LinearLayout>

總體布局設(shè)計(jì)還是狠清楚的,最后一個(gè) Button 則是用來退出登錄的。

2. 加載用戶頭像

用戶頭像的數(shù)據(jù)也是網(wǎng)絡(luò)數(shù)據(jù),加載用戶頭像,也就是獲取到圖像的 URL ,然后下載圖像,顯示在 CircleImageView 。

Picasso.with(getActivity()).load(url).into(imgHead);

圖像的下載就使用開源的 Picasso 圖像加載組件。

3. 添加頁(yè)面跳轉(zhuǎn)

上面的頭像部分完成了,下面就是下面的我的訂單、我的收藏、收貨地址以及我的消息的實(shí)現(xiàn)了,因?yàn)檫@四部分都是頁(yè)面的跳轉(zhuǎn),所以只要為其添加好點(diǎn)擊事件監(jiān)聽的處理——頁(yè)面跳轉(zhuǎn)。

private void initView() {

tvMyOders.setOnClickListener(this);
tvFavorite.setOnClickListener(this);
tvAddress.setOnClickListener(this);
tvNotification.setOnClickListener(this);

}

 @Override
    public void onClick(View view) {
        if(view.getId() == R.id.mine_layout_head){
            //我的訂單

        }
        else if(view.getId() == R.id.mine_tv_favorite){
            //我的收藏
        }
       else if(view.getId() == R.id.mine_tv_address){
            //收貨地址
        }
         else if(view.getId() == R.id.mine_tv_notification){
            //我的消息
        }
    }

這里僅僅是頁(yè)面跳轉(zhuǎn),至于我的訂單、我的收藏、收貨地址以及我的消息四大部分的具體實(shí)現(xiàn)后期會(huì)繼續(xù)介紹。

4.實(shí)現(xiàn)點(diǎn)擊登錄

點(diǎn)擊頭像上部區(qū)域,跳轉(zhuǎn)到登錄頁(yè)面,登錄的邏輯就先不要管了,登錄成功之后,自然要刷新頭像,并且修改頭像下的用戶名稱。

 @Override
    public void onClick(View view) {
        if(view.getId() == R.id.mine_layout_head){
            if(CNiaoApplicaiton.getInstance().getUser() == null) {
                Intent intent = new Intent(getContext(), LoginActivity.class);
                startActivityForResult(intent, Constants.REQUEST_CODE);
            }

        }
}

Constants.REQUEST_CODE 為請(qǐng)求碼,如果登錄成功了,則會(huì)設(shè)置 setResult(RESULT_OK); 并且回到我的頁(yè)面,這時(shí)候,我的頁(yè)面獲取到了來自登錄頁(yè)面的操作成功的結(jié)果碼的回調(diào)來刷新用戶信息,修改用戶信息的方法如下。

private void showUser(UserInfo user){

        if(user!=null){

            if(!TextUtils.isEmpty(user.getLogo_url()))
                showHeadImage(user.getLogo_url());

            tvUserName.setText(user.getUsername());

            btnLoginOut.setVisibility(View.VISIBLE);
        }
        else {
            imgHead.setImageResource(R.mipmap.default_head);
            tvUserName.setText(R.string.to_login);
            btnLoginOut.setVisibility(View.GONE);
        }
    }

UserInfo 為登錄后返回的用戶信息類,有用戶頭像、昵稱等成員。

5.實(shí)現(xiàn)退出登錄

退出登錄的話,就要把用戶的信息清理掉,然后刷新我的里面用戶信息的顯示。

 CNiaoApplicaiton.getInstance().clearUser();
showUser(null);

clearUser() 方法是清理整個(gè)應(yīng)用的用戶信息,等于當(dāng)前用戶未登錄,showUser(UserInfo user) 是修改用戶信息的,退出了登錄,就傳空了,顯示用戶未登錄時(shí)我的頁(yè)面的情況。

6.效果圖

運(yùn)行代碼,獲取效果圖。

上圖是登錄后的效果圖。

最終效果

最后來展示來最終的效果吧。

進(jìn)入我的頁(yè)面,默認(rèn)未登錄,點(diǎn)擊登錄,跳轉(zhuǎn)到登錄頁(yè)面,然后登錄成功,刷新顯示登錄的用戶頭像和昵稱等,再點(diǎn)擊退出登錄按鈕,我的頁(yè)面還原到未登錄效果。因?yàn)槭謾C(jī)號(hào)啥的不好展示,所以就直接從登錄頁(yè)面到登錄成功后的我的頁(yè)面了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容