友盟用户反馈自定义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 {

		@Override
		public int getCount() {
			return mComversation.getReplyList().size();
		}

		@Override
		public Object getItem(int arg0) {
			return mComversation.getReplyList().get(arg0);
		}

		@Override
		public long getItemId(int arg0) {
			return arg0;
		}

		@Override
		public int getViewTypeCount() {
			// 两种不同的Item布局
			return VIEW_TYPE_COUNT;
		}

		@Override
		public 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;
			}
		}

		@Override
		public 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并获取各种View
				holder = 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() {
		@Override
		public void handleMessage(Message msg) {
			adapter.notifyDataSetChanged();
		}
	};

然后是监听发送按钮的点击事件

sendBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String content = inputEdit.getText().toString();
				inputEdit.getEditableText().clear();
				if (!TextUtils.isEmpty(content)) {
					// 将内容添加到会话列表
					mComversation.addUserReply(content);
					//刷新新ListView
					mHandler.sendMessage(new Message());
					//数据同步
					sync();
				}
			}
		});

下拉刷新操作

// 下拉刷新
mSwipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
			@Override
			public void onRefresh() {
				sync();
			}
		});

sync方法为数据同步的方法,利用Comversation.sync方法来进行App端的数据与服务器端同步。该回调接口中onReceiveDevReply方法获得的replyList为开发者在友盟用户反馈Web端的回复。onSendUserReply方法获得的replyList则为本次同步数据中发送到服务器的用户反馈数据列表

// 数据同步
private void sync() {

		mComversation.sync(new SyncListener() {

			@Override
			public void onSendUserReply(List<Reply> replyList) {
			}

			@Override
			public void onReceiveDevReply(List<Reply> replyList) {
				// SwipeRefreshLayout停止刷新
				mSwipeRefreshLayout.setRefreshing(false);
				// 发送消息,刷新ListView
				mHandler.sendMessage(new Message());
				// 如果开发者没有新的回复数据,则返回
				if (replyList == null || replyList.size() < 1) {
					return;
				}
			}
		});
		// 更新adapter,刷新ListView
		adapter.notifyDataSetChanged();
	}

ListView Item的布局比较简单就不贴了,需要的话可以下载代码查看。

到这里一个利用友盟用户反馈SDK自定义的UI就实现了。

时间: 2024-10-11 09:52:03

友盟用户反馈自定义UI-Android的相关文章

如何使用友盟 Cocos2d-x 分享组件实现 Android/iOS 分享功能

Cocos2d-x作为一款优秀的跨平台游戏引擎,已经被越来越多的开发者使用,而在游戏中使用分享组件能够有效的提供用户粘性,通过分享回流来提高APP安装量,但是目前市面上能够在Cocos2d-x环境下使用的分享插件并不多,开发者们只能自己对原生分享SDK进行封装来实现,前一段时间友盟推出Cocos2d-x分享组件,能够帮助开发者快速集成.友盟也把组件的源码放在GitHub上,有好的想法也可以直接在GitHub上修改(PS.在GitHub上提bug可以获得友盟的小奖品),同样也可以对源码进行学习,对

打造高仿QQ的友盟反馈界面(MVP模式)

什么是MVP呢,简单来说就是将view层和逻辑完全独立出来,让逻辑和显示完全独立.本例中就是采用了这种模式,让activity作为view层,activity中涉及了适配器,所以这里尝试让适配器作为P层来进行逻辑处理.以后可能要考虑用多个p来做逻辑处理.总之,我们先来分析下如何用MVP得思路来分析这个工程吧~ 一.界面 界面这个环节有很多细节需要扣,之前我写过一篇文章就是讲这个界面实现的,推荐先去看看:http://www.cnblogs.com/tianzhijiexian/p/4295195

集成友盟的意见反馈功能

最近一直在开发毕业设计的项目,其中用到了很多自己没接触过的东西,就包括集成友盟SDK的意见反馈模块的内容了.确实用了一点心思在里面,捣鼓了一阵子,中间也遇到了一些问题,关键这问题也不好解决,问大神大神也不一定有去接触这一块,然后网上是有很多资料,但总感觉对我的帮助不是很大,所以,当完成了友盟的这块功能后,就特别想贡献出来,一是为以后方便自己重温这块知识点,二是顺便 发布出来帮助像我这样遇到问题一直寻求解决办法的人.好了,废话不多说了,直接上效果图,然后PO代码! 效果图如下: 当然顺便也po上友

Android 云服务器的搭建和友盟APP自动更新功能的实现

setContentView(R.layout.activity_splash); //Bmob SDK初始化--只需要这一段代码即可完成初始化 //请到Bmob官网(http://www.bmob.cn/)申请ApplicationId,具体地址:http://docs.bmob.cn/android/faststart/index.html?menukey=fast_start&key=start_android Bmob.initialize(this, Constant.BMOB_APP

友盟推出“数据工场”助跑开发者,“用户评级”和“微社区”齐亮相

今天,友盟推出了新战略“友盟数据工场”和数据产品“用户评级”.业界500多名开发者与我们一同见证了这一时刻.在此,感谢大家的支持!同时,想把我们最新的动态分享给所有盟友. “数据工场”能给开发者带来什么价值? 友盟高级技术总监叶谦介绍了“数据工场”的运转流程,其挖掘系统构建在开源大数据处理平台,通过设备识别.行为分析.设备评级等手段,日夜不停地对近十亿移动设备数据进行挖掘和分析,产出包括用户属性标签.用户兴趣标签.用户地理位置 POI .移动设备标识体系在内的多个数据成果. 这些数据挖掘成果将不

umeng用户反馈

在已有项目中集成友盟意见反馈功能 1) 拷贝lib_Umeng_feedback库的清单文件中的资源 a) application b) 权限 c) 清单中的Activity/Service/Boradcast d) appkey配置 2) 在意见反馈事件中调用 new FeedbackAgent(this).startFeedbackActivity(); 注意点: 删除之前的support v4旧的架包, 添加新的架包,然后确保每个都更新为新的架包. 注册后获得key值,清单文件中修改为自己

UMeng SDK(友盟) 之 用户反馈

好久没有更新了...忙于大学毕业的那些事(写论文,答辩,吃饭,拍照,喝酒,找租房,搬家...) 已然毕业,好好回归自己的职业.深入底层,不漂流于浮表. ok.切入正题:使用的是UMeng的移动开发SDK.收集用户反馈是通过友盟开发者的应用管理后台. 首先是继承android平台的. http://dev.umeng.com/feedback/android/quick-start 通过这个集成指南的地址,我顺利的完成了最基本的功能需求. 首先是添加jar包依赖,以及将res文件夹中的资源copy

android 集成友盟分享之后,想自定义分享面板的看过来

第一种情况 首先上传一张默认的友盟分享的效果图 看起来还不错,但是总是有这样那样的原因,需要我们对默认效果做出一些改变. 第二种情况 如果你想做出下面的效果: 或者这样的效果 : 总之上面的效果总是在默认的基础上(及原有的控件基础上做出改变,改变颜色,背景,背景颜色等等一些基本的改变), 如果你真的遇到了这样的需求很简单:你可以直接登录友盟的开发文档中有十分详细的介绍,很简单的 下面是一些截图: 好,截图结束. 你可以直接进去看. 第三章情况 有了前两种情况,如果还没有满足你的需求,那么咱们今天

android使用友盟实现第三方登录、分享以及微信回调无反应问题解决办法

        Leaning_wk每一次的进步都会拉近与成功的距离! 帐号设置退出   关闭 qq_15855289的博客 目录视图 摘要视图 订阅 异步赠书:Kotlin领衔10本好书      免费直播:AI时代,机器学习如何入门?      程序员8月书讯      每周荐书:Java Web.Python极客编程(评论送书) android使用友盟实现第三方登录.分享以及微信回调无反应问题解决办法 标签: android友盟第三方登录分享微信登录回调问题 2017-02-10 16:2