MyFlag Step6:app详细页面设计与代码编写

来源:互联网 发布:迪杰斯特拉算法原理 编辑:程序博客网 时间:2024/06/05 17:10

引言

这周前半部分的工作我们主要对页面进行了初步设计,也实现了一些功能代码,后半部分在页面方面进行了进一步的详细设计,并且编写了其他功能代码,总结一下工作目录:

  • 页面详细设计与所有页面基本完成
  • 客户端代码编写
  • 后台代码编写

在这里,我对自己主要从事的工作,即客户端代码的编写,具体来说是查看好友界面及内部处理逻辑的编写,做一个着重的介绍。


一、界面编写


在之前的界面设计中,设计出的界面如下所示




经过分析,发现该界面的最主要的内容是好友的列表,因此考虑使用两个嵌套的ListView组件实现。但是,用户的分组是通过字母进行的,故外层的ListView实现起来会比较复杂。因此,我考虑自定义一个LetterFilterListView控件,继承ListView,实现了用侧边字母进行好友检索的功能,代码如下:


package com.example.sdu.myflag.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.SectionIndexer;/** * 字母控件 */@SuppressWarnings("ResourceType")public class LetterFilterListView extends RelativeLayout {    /**     * The context.     */    private Context mContext;    /**     * The section indexter.     */    private SectionIndexer mSectionIndexter = null;    /**     * The list view.     */    private ListView mListView;    /**     * The letter view.     */    private LetterView mLetterView;    /**     * The selectedLetter view     */    private LetterSelectedView mLetterSelectedView;    public LetterFilterListView(Context context) {        this(context, null);    }    public LetterFilterListView(Context context, AttributeSet attrs) {        this(context, null, 0);    }    public LetterFilterListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    private void init(Context context) {        this.mContext = context;    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        int count = getChildCount();        /** 必须包括一个子 View */        if (count < 1) {            throw new IllegalArgumentException("this layout must contain 1 child views,and AdapterView  must in the first position!");        }        View view = this.getChildAt(0);        AdapterView<?> adapterView = null;        if (view instanceof AdapterView<?>) {            adapterView = (AdapterView<?>) view;            mListView = (ListView) adapterView;            mSectionIndexter = (SectionIndexer) mListView.getAdapter();            /** 右边的字母显示 */            mLetterView = new LetterView(mContext);            mLetterView.setListView(mListView);            mLetterView.setId(5000);//为了下面的控件布局            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(60, ViewGroup.LayoutParams.WRAP_CONTENT);            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);            layoutParams.topMargin = 10;            layoutParams.rightMargin = 10;            layoutParams.bottomMargin = 10;            this.addView(mLetterView, layoutParams);            /** 点击右边的字母后显示选中的字母 */            mLetterSelectedView = new LetterSelectedView(mContext);            RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(30, ViewGroup.LayoutParams.WRAP_CONTENT);            layoutParams1.topMargin = 10;            layoutParams1.rightMargin = 10;            layoutParams1.bottomMargin = 10;            layoutParams1.addRule(RelativeLayout.LEFT_OF, mLetterView.getId());            this.addView(mLetterSelectedView, layoutParams1);        }        /** 必须包括一个子 AdapterView,一般就是 ListView */        if (adapterView == null) {            throw new IllegalArgumentException("must contain a AdapterView in this layout!");        }    }    /**     * 右边字母显示 View     *     * @author liuyinjun     * @date 2015-3-16     */    private class LetterView extends View {        /**         * The list.         */        private ListView mListView;        /**         * The letter.         */        private char[] mLetter;        /**         * The paint.         */        private Paint mPaint;        /**         * The width center.         */        private float mWidthCenter;        /**         * 字母之间的间距.         */        private float mSingleHeight;        public LetterView(Context context) {            this(context, null);        }        public LetterView(Context context, AttributeSet attrs) {            this(context, attrs, 0);        }        public LetterView(Context context, AttributeSet attrs, int defStyle) {            super(context, attrs, defStyle);            init();        }        /**         * 初始化.         */        private void init() {            mLetter = new char[]{'#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};            mPaint = new Paint();            mPaint.setColor(Color.parseColor("#949494"));            mPaint.setTypeface(Typeface.DEFAULT_BOLD);            mPaint.setTextSize(22);            mPaint.setAntiAlias(true);            mPaint.setTextAlign(Paint.Align.CENTER);        }        @Override        protected void onDraw(Canvas canvas) {            super.onDraw(canvas);            float height = getHeight();            mSingleHeight = height / mLetter.length;            mWidthCenter = getMeasuredWidth() / (float) 2;            for (int i = 0; i < mLetter.length; i++) {                canvas.drawText(String.valueOf(mLetter[i]), mWidthCenter, mSingleHeight + (i * mSingleHeight), mPaint);            }        }        /**         * Gets the list view.         *         * @return the list view         */        public ListView getListView() {            return mListView;        }        /**         * Sets the list view.         *         * @param listView the new list view         */        public void setListView(ListView listView) {            this.mListView = listView;        }        public boolean onTouchEvent(MotionEvent event) {            super.onTouchEvent(event);            int index = 0;//点击的位置在 mLetters 中的索引            int i = (int) event.getY();            int div = (int) mSingleHeight;            /** 重新计算出索引 */            if (div != 0) {                index = i / div;            }            if (index >= mLetter.length) {                index = mLetter.length - 1;            } else if (index < 0) {                index = 0;            }            switch (event.getAction()) {                case MotionEvent.ACTION_UP:                    break;                case MotionEvent.ACTION_DOWN:                case MotionEvent.ACTION_MOVE:                    mLetterSelectedView.setViewY(mSingleHeight + (index * mSingleHeight));//设置选中字母显示的Y轴坐标位置                    mLetterSelectedView.setSelectedLetter(mLetter[index]);//设置选中的字母                    if (mLetterSelectedView.getVisibility() == View.GONE)//若控件为隐藏状态,则显示                        mLetterSelectedView.setVisibility(View.VISIBLE);                    /** 显示1s后消失*/                    mLetterSelectedView.postDelayed(new Runnable() {                        @Override                        public void run() {                            // TODO Auto-generated method stub                            mLetterSelectedView.setVisibility(View.GONE);                        }                    }, 1000);                    if (mListView.getAdapter() != null) {                        ListAdapter listAdapter = (ListAdapter) mListView.getAdapter();                        if (mSectionIndexter == null) {                            mSectionIndexter = (SectionIndexer) listAdapter;                        }                        int position = mSectionIndexter.getPositionForSection(mLetter[index]);                        if (position == -1) {//列表中没有首字母为选中字母的的项                            return true;                        }                        mListView.setSelection(position);                    }            }            return true;        }    }    /**     * 点击右边字母后显示的出的加大字母     *     * @author liuyinjun     * @date 2015-3-16     */    private class LetterSelectedView extends View {        private Paint mPaint;        /**         * 选中的字母         */        private char mLetter = 'A';        /**         * 绘制字母的Y轴坐标         */        private float mY;        public LetterSelectedView(Context context) {            this(context, null);        }        public LetterSelectedView(Context context, AttributeSet attrs) {            this(context, attrs, 0);        }        public LetterSelectedView(Context context, AttributeSet attrs, int defStyle) {            super(context, attrs, defStyle);            init();        }        private void init() {            mPaint = new Paint();            mPaint.setColor(Color.parseColor("#ff55bb22"));            mPaint.setTypeface(Typeface.DEFAULT_BOLD);            mPaint.setTextSize(35);            mPaint.setAntiAlias(true);            mPaint.setTextAlign(Paint.Align.CENTER);        }        @Override        protected void onDraw(Canvas canvas) {            super.onDraw(canvas);            canvas.drawText(String.valueOf(mLetter), getMeasuredWidth() / (float) 2, mY, mPaint);        }        public void setSelectedLetter(char letter) {            this.mLetter = letter;            this.invalidate();//刷新控件        }        public void setViewY(float y) {            this.mY = y;        }    }}

可以看到,该类继承自ListView,自然具有ListView的功能,又重写了父类的方法,增加了按照首字母进行排序的功能。这样一来,使用该自定义类就可自动完成按照首字母的排序要求。

在此基础上,写出的xml布局文件如下所示。


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="#fffafafa"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="?attr/actionBarSize"        android:background="@color/white">        <ImageButton            android:id="@+id/back_btn"            android:layout_width="?attr/actionBarSize"            android:layout_height="?attr/actionBarSize"            android:layout_alignParentLeft="true"            android:onClick="FriendBack"            android:background="@drawable/toolbar_back_bg"            android:src="?attr/homeAsUpIndicator" />        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:text="好友"            android:textColor="@color/black"            android:textSize="19sp" />        <Button            android:id="@+id/complete_btn"            android:layout_width="?attr/actionBarSize"            android:layout_height="?attr/actionBarSize"            android:layout_alignParentRight="true"            android:text="完成"            android:textSize="15sp"            android:textColor="@color/login_button_default_blue"            android:background="@drawable/toolbar_back_bg"            android:src="?attr/homeAsUpIndicator" />    </RelativeLayout>    <com.example.sdu.myflag.widget.LetterFilterListView        android:id="@+id/letterView"        android:layout_width="wrap_content"        android:layout_height="fill_parent"        android:focusable="true"        android:focusableInTouchMode="true">        <ListView            android:id="@+id/listView"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:layout_gravity="center"            android:cacheColorHint="#00000000"            android:divider="@null"/>    </com.example.sdu.myflag.widget.LetterFilterListView></LinearLayout>

二、内部处理逻辑代码编写


在之前的详细设计中,已经完成了该功能的详细设计,UML活动图如下所示



根据详细设计,定义了类FriendActivity,具体代码如下所示:

package com.example.sdu.myflag.activity;import android.content.Intent;import android.content.SharedPreferences;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.ListView;import android.widget.Toast;import com.example.sdu.myflag.R;import com.example.sdu.myflag.adapter.FriendListAdapter;import com.example.sdu.myflag.base.BaseActivity;import com.example.sdu.myflag.base.BaseApplication;import com.example.sdu.myflag.bean.FriendBean;import com.example.sdu.myflag.util.CharacterParser;import com.example.sdu.myflag.util.NetUtil;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.List;import okhttp3.Response;/** * 好友列表界面 */public class FriendActivity extends BaseActivity {    private ListView listView;    private FriendListAdapter friendListAdapter;    int code;    Button complete;    @Override    public int getLayoutId() {        return R.layout.activity_friend;    }    @Override    public void afterCreate(Bundle savedInstanceState) {        listView = (ListView) findViewById(R.id.listView);        code = getIntent().getIntExtra("code", 0);        complete = (Button) findViewById(R.id.complete_btn);        complete.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent();                intent.putExtra("selected", friendListAdapter.getSelected());                setResult(1, intent);                FriendActivity.this.finish();            }        });        if (code == 0)            complete.setVisibility(View.GONE);        getData();    }    private void getData() {        SharedPreferences sp = BaseApplication.getInstance().getSharedPreferences("User", MODE_PRIVATE);        String id = sp.getString("uid", "");        ArrayList<NetUtil.Param> params = new ArrayList<>();        params.add(new NetUtil.Param("id", id));        try {            NetUtil.getResult(NetUtil.getFriendListUrl, params, new FriendListCallBack());        } catch (IOException e) {            e.printStackTrace();        }    }    public void FriendBack(View view) {        this.finish();    }    class FriendListCallBack implements NetUtil.CallBackForResult {        @Override        public void onFailure(IOException e) {            FriendActivity.this.runOnUiThread(new Runnable() {                @Override                public void run() {                    Toast.makeText(FriendActivity.this, "获取好友列表失败", Toast.LENGTH_SHORT).show();                }            });        }        @Override        public void onSuccess(final Response response) {            if (response.isSuccessful()) {                try {                    final String res = response.body().string();                    FriendActivity.this.runOnUiThread(new Runnable() {                        @Override                        public void run() {                            JSONArray jsonArray = null;                            try {                                JSONObject friend = new JSONObject(res);                                jsonArray = friend.getJSONArray("friend");                                ArrayList<FriendBean> list = new ArrayList<>();                                CharacterParser characterParser = new CharacterParser();                                for (int i = 0; i < jsonArray.length(); i++) {                                    JSONObject jsonObject = jsonArray.getJSONObject(i);                                    String nickname = jsonObject.optString("nickname");                                    String remark = jsonObject.optString("remark");                                    String uid = jsonObject.optString("uid");                                    int iconId = jsonObject.optInt("photo");                                    String pinYin = characterParser.getSelling(nickname);                                    String sortString = pinYin.substring(0, 1).toUpperCase();                                    String firstLetter = "";                                    if (sortString.matches("[A-Z]")) {                                        firstLetter = sortString.toUpperCase();                                    } else {                                        firstLetter = "#";                                    }                                    list.add(new FriendBean(uid, nickname, firstLetter, remark, iconId));                                }                                Collections.sort(list);                                friendListAdapter = new FriendListAdapter(FriendActivity.this, list, code);                                listView.setAdapter(friendListAdapter);                            } catch (JSONException e) {                                e.printStackTrace();                            }                        }                    });                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

三、总结

总体来说,这两天的还是不错的,虽然只实现了一个功能,但毕竟对ListView组件进行了重写,还是有一定的工作量的。好友也算一个比较复杂的部分,解决了好友功能,相信之后的工作会更加顺利。



原创粉丝点击