友盟使用者反饋自訂UI-Android,使用者反饋ui-android
友盟使用者反饋SDK是友盟為開發人員提供的組件之一,使用者反饋也是每款應用必不可少的模組。如果你想方便的收集使用者的反饋建議,並且與發送反饋的使用者進行溝通交流,那麼友盟使用者反饋SDK是你不錯的選擇,使用友盟使用者反饋SDK兩行代碼實現開發人員和使用者輕鬆高效溝通。從友盟BBS看到許多開發人員都希望通過自訂UI,來實現使用者反饋功能。下面就為大家來講解如何使用友盟使用者反饋SDK來制定UI。這裡以一個demo來說明。
首先,這是自訂的UI介面:
註:部分資源檔來源於某開源App
使用友盟使用者反饋的資料介面,首先需要瞭解,SDK都提供了那些介面。根據整合文檔,我們可以知道,對於使用者反饋SDK來說,使用者和開發人員或者客服交流的整個內容是一個Conversation,其中包含了使用者的反饋、追問以及客服的回複,而整個Conversation是由Reply組成的,使用者的一條反饋或者是客服的一條回複都是一個Reply,每個Reply都有一些屬性來表明Reply的各種資訊。其中有:
type :
Reply.TYPE_DEV_REPLY : 表示這是一條開發人員的回複
Reply.TYPE_SUER_REPLY : 表示這是一條使用者的回複
Reply.TYPE_NEW_FEEDBACK : 表示這是一條反饋 相當於使用者的第一條回複
status:
Reply.STATUS_NOT_SENT :表示該條回複沒有發送成功或者還未發送
Reply.STATUS_SENDING :表示該條回複正在發送
Reply.STATUS_SENT :表示該條回複已發送成功
created_at : 表示回複的時間,以毫秒為單位
Conversation類提供了getReplyList()方法來擷取整個會話的內容,返回的是List<Reply>,同時也提供了addUserReply()方法,將用反饋內容加入到Conversation,那麼Conversation執行個體怎麼得到呢?
FeedbackAgent類中提供了一個getDefaultConversation()方法來擷取預設的Conversation(),對於不需要建立多個會話的App來講有這個就夠了。
最重要的一個介面:
Comversation.sync()方法,該方法實現了資料的同步,即可以通過該方法發送使用者反饋、回複也可以通過該方法擷取來自開發人員的回複。下面會詳細介紹。
另外FeedbackAgent介面也提供了setUserInfo()方法來設定使用者資訊,以及getUserInfo()方法擷取使用者資訊,關於使用者資訊的操作方法可以查看友盟使用者反饋SDK整合文檔,這裡不做示範。
瞭解了這些,下面我們就開始劈裡啪啦敲代碼。
第一步當然是布局了,下面是自訂會話介面的布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/fb_input_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical" > <View android:layout_width="match_parent" android:layout_height="@dimen/umeng_fb_item_line_height" android:background="@color/umeng_fb_line" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:orientation="horizontal" android:paddingBottom="8dp" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="8dp" > <Button android:id="@+id/fb_send_btn" android:layout_width="70dp" android:layout_height="33dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:background="@drawable/fb_send_btn_bg" android:gravity="center" android:text="@string/umeng_fb_send" android:textColor="@android:color/white" android:textSize="16sp" /> <EditText android:id="@+id/fb_send_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:layout_toLeftOf="@id/fb_send_btn" android:layout_toStartOf="@id/fb_send_btn" android:background="@drawable/fb_input_bg" android:hint="@string/umeng_fb_feedback" android:minHeight="33dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:scrollbars="vertical" android:textSize="16sp" /> </RelativeLayout> </LinearLayout> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/fb_reply_refresh" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/fb_input_layout" > <ListView android:id="@+id/fb_reply_list" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@null" android:listSelector="#00000000" > </ListView> </android.support.v4.widget.SwipeRefreshLayout></RelativeLayout>
布局檔案就不多說了,這裡包含了一個ListView來展示整個會話內容,還有一個輸入框和發送按鈕。
然後在Activity中開始利用友盟使用者反饋SDK的資料介面幹活。
要實現UI,這些View自然是少不了的
mListView = (ListView) findViewById(R.id.fb_reply_list);sendBtn = (Button) findViewById(R.id.fb_send_btn);inputEdit = (EditText) findViewById(R.id.fb_send_content);//下拉重新整理組件mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.fb_reply_refresh);
擷取Conversation對象,所有會話資料都在這裡
Conversation mComversation = new FeedbackAgent(this).getDefaultConversation();
然後為ListView建立Adapter,代碼比較簡單,直接看注釋吧
class ReplyAdapter extends BaseAdapter {@Overridepublic int getCount() {return mComversation.getReplyList().size();}@Overridepublic Object getItem(int arg0) {return mComversation.getReplyList().get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}@Overridepublic int getViewTypeCount() {// 兩種不同的Item布局return VIEW_TYPE_COUNT;}@Overridepublic int getItemViewType(int position) {// 擷取單條回複Reply reply = mComversation.getReplyList().get(position);if (Reply.TYPE_DEV_REPLY.equals(reply.type)) {// 開發人員回複Item布局return VIEW_TYPE_DEV;} else {// 使用者反饋、回複Item布局return VIEW_TYPE_USER;}}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;// 擷取單條回複Reply reply = mComversation.getReplyList().get(position);if (convertView == null) {// 根據Type的類型來載入不同的Item布局if (Reply.TYPE_DEV_REPLY.equals(reply.type)) {// 開發人員的回複convertView = LayoutInflater.from(mContext).inflate(R.layout.custom_fb_dev_reply, null);} else {// 使用者的反饋、回複convertView = LayoutInflater.from(mContext).inflate(R.layout.custom_fb_user_reply, null);}// 建立ViewHolder並擷取各種Viewholder = new ViewHolder();holder.replyContent = (TextView) convertView.findViewById(R.id.fb_reply_content);holder.replyProgressBar = (ProgressBar) convertView.findViewById(R.id.fb_reply_progressBar);holder.replyStateFailed = (ImageView) convertView.findViewById(R.id.fb_reply_state_failed);holder.replyData = (TextView) convertView.findViewById(R.id.fb_reply_date);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 以下是填充資料// 設定Reply的內容holder.replyContent.setText(reply.content);// 在App介面,對於開發人員的Reply來講status沒有意義if (!Reply.TYPE_DEV_REPLY.equals(reply.type)) {// 根據Reply的狀態來設定replyStateFailed的狀態if (Reply.STATUS_NOT_SENT.equals(reply.status)) {holder.replyStateFailed.setVisibility(View.VISIBLE);} else {holder.replyStateFailed.setVisibility(View.GONE);}// 根據Reply的狀態來設定replyProgressBar的狀態if (Reply.STATUS_SENDING.equals(reply.status)) {holder.replyProgressBar.setVisibility(View.VISIBLE);} else {holder.replyProgressBar.setVisibility(View.GONE);}}// 回複的時間資料,這裡仿照QQ兩條Reply之間相差100000ms則展示時間if ((position + 1) < mComversation.getReplyList().size()) {Reply nextReply = mComversation.getReplyList().get(position + 1);if (nextReply.created_at - reply.created_at > 100000) {Date replyTime = new Date(reply.created_at);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");holder.replyData.setText(sdf.format(replyTime));holder.replyData.setVisibility(View.VISIBLE);}}return convertView;}class ViewHolder {TextView replyContent;ProgressBar replyProgressBar;ImageView replyStateFailed;TextView replyData;}}
建立Adapter並為ListView設定Adapter
adapter = new ReplyAdapter();mListView.setAdapter(adapter);
會話列表完成了,接下來是發送反饋和App端與伺服器資料的同步。
建立Handler對象來實現資料的重新整理,用於Conversation或者Reply有更新時,重新整理ListView。
private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {adapter.notifyDataSetChanged();}};
然後是監聽發送按鈕的點擊事件
sendBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String content = inputEdit.getText().toString();inputEdit.getEditableText().clear();if (!TextUtils.isEmpty(content)) {// 將內容添加到會話列表mComversation.addUserReply(content);//重新整理新ListViewmHandler.sendMessage(new Message());//資料同步sync();}}});
下拉重新整理操作
// 下拉重新整理mSwipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() {@Overridepublic void onRefresh() {sync();}});
sync方法為資料同步的方法,利用Comversation.sync方法來進行App端的資料與伺服器端同步處理。該回調介面中onReceiveDevReply方法獲得的replyList為開發人員在友盟使用者反饋Web端的回複。onSendUserReply方法獲得的replyList則為本次同步資料中發送到伺服器的使用者反饋資料列表
// 資料同步private void sync() {mComversation.sync(new SyncListener() {@Overridepublic void onSendUserReply(List<Reply> replyList) {}@Overridepublic void onReceiveDevReply(List<Reply> replyList) {// SwipeRefreshLayout停止重新整理mSwipeRefreshLayout.setRefreshing(false);// 發送訊息,重新整理ListViewmHandler.sendMessage(new Message());}});// 更新adapter,重新整理ListViewadapter.notifyDataSetChanged();}
ListView Item的布局比較簡單就不貼了,需要的話可以下載代碼查看。
到這裡一個利用友盟使用者反饋SDK自訂的UI就實現了。
工程