上一次的博文中详细分析了基金项目的整体架构和主界面的UI设计。今天分享地方是剩下的3个页面及相应功能的实现。
#个人中心
个人中心界面,最开始会跳转到一个登陆界面,用户可以通过选择“身份证、基金账户、护照、户口本“,然后输入相应的账号和密码进行登陆。在这个界面中,还具有相应的记住密码,忘记密码功能。不输入是不允许进入账户的,当正确输入相应的账号密码后,通过和后台服务器进行验证登陆,登陆进去之后是一个账户详情页,有持仓查询、盈亏查询、交易查询等功能,在持仓查询中hi有总资产,活期宝、今年收益的详细信息。在下面通过一个listview展示自己已买基金的名称、收益率、代号等信息。
#交易界面
在这个页面中,若用户未登录,则在该页面最上方会提示:您还未登录”同时在右上角会有一个登陆按钮,通过点击该按钮可跳转至登陆页面。在交易页面,有充值、快速提现、查询等操作。
private class MySpinnerAdapter extends BaseAdapter implements SpinnerAdapter { @Override public int getCount() { return mListData.size(); } @Override public Object getItem(int position) { return mListData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.my_simple_spinner_item_recharge, null); } TextView view = (TextView) convertView .findViewById(R.id.recharge_spinner_view); view.setText(mListData.get(position).getName()); if (mListData.get(position).getSupport_withhold() == 1) { view.setEnabled(true); } else { view.setEnabled(false); } return convertView; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.my_simple_spinner_dropdown_item_recharge, null); } CheckedTextView view = (CheckedTextView) convertView.findViewById(R.id.recharge_spinner_item); view.setText(mListData.get(position).getName()); if (mListData.get(position).getSupport_withhold() == 1) { view.setEnabled(true); view.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(R.drawable.icon_withhold), null); } else { view.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); view.setEnabled(false); } return convertView; } }
#帮助界面
最后一个节目就是一个帮助界面了,这里有消息中心、帮助、意见反馈、关于我们。当点击拨打客服电话后,会跳转到电话拨打界面。
/** * 获取帮助消息 */ private Handler getHelpsHandler = new Handler() { public void handleMessage(Message msg) { dismissProgressDialog(); switch (msg.what) { case BaseHandlerUI.TASK_NOTIFY_RETURN_DATA: if (msg.obj != null) { try { bean = (GetHelpsResultBean) msg.obj; if (bean.state.equals("0")) { mDatabaseAdapter.open_fund(); mDatabaseAdapter.deleteAllHelpsData(); List<TreeViewAdapter.TreeNode> treeNode = adapter.GetTreeNode(); treeNode.clear(); for (int i = 0; i < bean.list.size(); i++) { mDatabaseAdapter.insertHelpsData(bean.list.get(i).ask, bean.list.get(i).reply); TreeViewAdapter.TreeNode node = new TreeViewAdapter.TreeNode(); node.parent = bean.list.get(i).ask; for (int ii = 0; ii < 1; ii++) { node.childs.add(bean.list.get(i).reply); } treeNode.add(node); } adapter.UpdateTreeNode(treeNode); expandableList.setAdapter(adapter); mDatabaseAdapter.close_funds(); } } catch (Exception e) { e.printStackTrace(); } } else { } break; } } };
#异步任务类
我们都知道,在安卓的应用开发中,子线程是不能直接操作主线程的,所以,如果有耗时操作 又或者是密集操作,就只能放在子线程中去处理,但是,如果处理后的结果需要更改UI的显示内容,这时候,就只能使用handler或AsyncTask进行处理。
AsyncTask是一个异步任务类,可以很容易在子线程中处理耗时操作。里面包含三个泛型参数params、progress、result,分别表示:
1.params:在执行asynctack时需要传入的参数,可用于后台任务中使用。
2.progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3.result:当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
一个简单的泛型类如下:
<span style="font-size:18px;">class DownloadTask extends AsyncTask<Void,Integer,Boolean>{}</span>
public HttpRequestAsyncTask(HttpRequestInfo request, TaskListener listener, Context context) { this.context = context; request.putParam("device_info", ConfigUtil.getImei(context)) .putParam("app_version", ConfigUtil.getVersionName(context)) .putParam("market", context.getString(R.string.channel_str)); mListener = listener; mRequest = request; } public HttpRequestAsyncTask(HttpRequestInfo request, TaskListenerWithState taskListenerWithState, Context context) { this.context = context; request.putParam("device_info", ConfigUtil.getImei(context)) .putParam("app_version", ConfigUtil.getVersionName(context)) .putParam("market", context.getString(R.string.channel_str)); mListenerWithState = taskListenerWithState; mRequest = request; } @Override protected HttpResponseInfo doInBackground(Void... params) { if (!ConfigUtil.isConnect(context)) { return new HttpResponseInfo(null, HttpTaskState.STATE_NO_NETWORK_CONNECT); } try { if (mRequest != null) { if (mRequest.getRequestID() == -2) { return new HttpResponseInfo( HttpManager.postHttpRequest(mRequest), HttpTaskState.STATE_OK); } return new HttpResponseInfo( HttpManager.postHttpsRequest(mRequest), HttpTaskState.STATE_OK); } } catch (SocketTimeoutException e) { e.printStackTrace(); return new HttpResponseInfo("{"result":"3"}", HttpTaskState.STATE_OK); } catch (UnknownHostException e) { e.printStackTrace(); return new HttpResponseInfo("{"result":"3"}", HttpTaskState.STATE_OK); } catch (Exception e) { e.printStackTrace(); return new HttpResponseInfo("{"result":"3"}", HttpTaskState.STATE_OK); } return null; }
#HTTP编程
Http编程有请求和响应,这里我们把对json数据年度解析放到这一部分来讲解:
/** * Http 请求 */ public class HttpRequestInfo { public static final String TAG = "HttpRequestInfo"; /* Http 请求的 URL */ private String requestUrl; private int requestID; private Map<String, String> requestParams; public HttpRequestInfo(String url) { this.setRequestUrl(url); requestParams = new HashMap<String, String>(); } public HttpRequestInfo(String url, Map<String, String> params) { this.setRequestUrl(url); this.setRequestParams(params); } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } public Map<String, String> getRequestParams() { return requestParams; } public void setRequestParams(Map<String, String> requestParams) { this.requestParams = requestParams; } public String getParamsStr() { String str = ""; if (requestParams != null) { for (Entry<String, String> entry : requestParams.entrySet()) { String key = entry.getKey(); String val = entry.getValue(); key = URLEncoder.encode(key); val = URLEncoder.encode(val); str += key + "=" + val + "&"; } } if (str.equals("")) { return null; } LogUtil.i(TAG, this.requestUrl + str); return str; } public HttpRequestInfo putParam(String key, String value) { this.requestParams.put(key, value); return this; } public int getRequestID() { return requestID; } public void setRequestID(int requestID) { this.requestID = requestID; } }对于响应:
/** * Http 响应 */ public class HttpResponseInfo { public enum HttpTaskState { STATE_OK, STATE_NO_NETWORK_CONNECT, STATE_TIME_OUT, STATE_UNKNOWN, } public HttpResponseInfo(String result, HttpTaskState state) { this.result = result; this.state = state; } private HttpTaskState state; private String result; public HttpTaskState getState() { return state; } public void setState(HttpTaskState state) { this.state = state; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } }
数据库是一个非常重要的知识点,这里主要是分享一个这个基金中的数据库,这个数据库是一个小型的轻量级的数据库,
SQLiteOpenHelper有onCreate()、onUpgrade()两个方法。
private static class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHelper(Context context, String name, CursorFactory factory, int version) { super(context, DB_NAME, null, version); } @Override public void onCreate(SQLiteDatabase db) { //创建所有数据库表 db.execSQL(DB_CREATE_FUND); db.execSQL(DB_CREATE_FAV_FUND); db.execSQL(DB_CREATE_HELPS_INFO); db.execSQL(DB_CREATE_FUND_DETAIL); db.execSQL(DB_CREATE_MSG); } // 更新基金数据 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_FUND); db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_FAV_FUND); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_HELPS_INFO); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_FUND_DETAIL); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_MSG); onCreate(db); } }
当然了,仅仅通过一篇博文是不可逆完全完整的说完整个项目了,这里写的仅仅是冰山一角,更多的内容还是希望读者自己去发现并学到里面的精华部分!当然咯,我相信有一部分人读了也基本上没看懂我写的是什么,那么请下载源码看看,互相学习咯!
源码下载地址:http://download.csdn.net/detail/sdksdk0/9461193