首页 > 代码库 > 低门槛入门——图灵机器人开发
低门槛入门——图灵机器人开发
空暇之余。想到上次看过的一个图灵机器人开发视频。直接上其官网看开发人员手冊,自己动手写了一个图灵机器人小应用。编写的思路基本和网上的一些开发视频不谋而合,都是网络訪问+json解析,再者就是设计出好看的界面。有兴趣的同学能够依据自己的需求进行更改甚至细化里面的查询功能,全然能够做出一款完整的app应用。
先上图看看我的demo效果:
这个项目主要包含三个部分:UI设计与开发、调用图灵API获取数据json解析封装成Bean、listview的优化显示。
UI设计与开发
先看下整个xml的UI布局
布局非常简单,从左上角能够看到整个布局的排版。这对于android开发人员来说非常easy,当中listview使用了下面设置是为了填满中间空间。
android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"
使用圆角的边缘shape文件(拿EditText为例)
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:endColor="#ffffff" android:startColor="#ffffff" /> <corners android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" android:topLeftRadius="5dp" android:topRightRadius="5dp" /> <stroke android:width="1dip" android:color="#ffffff" /> </shape>
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/start_clickafter" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/start_clickafter" /> <item android:state_selected="true" android:drawable="@drawable/start_clickafter" /> <item android:state_focused="true" android:drawable="@drawable/start_clickafter" /> <!-- 默认时的背景图片--> <item android:state_focused="false" android:drawable="@drawable/start_clickbefore" /> </selector>
对于聊天框的配置,我们须要实现左边和右边聊天框效果(例如以下图所看到的)
我们须要配置左右两个xml布局。
左布局例如以下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/id_time" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="10sp" android:layout_alignParentTop="true" android:gravity="center"/> <com.example.yummylau.turingrobot.ui.CircularImage android:layout_below="@+id/id_time" android:id="@+id/id_iv" android:layout_width="50dp" android:layout_height="50dp" android:padding="10dp" /> <TextView android:layout_below="@+id/id_time" android:layout_marginTop="10dp" android:layout_marginLeft="5dp" android:layout_marginRight="50dp" android:layout_toRightOf="@+id/id_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_tv" android:gravity="center_vertical" android:textSize="17sp" android:background="@drawable/aio_friend_bg_nor_11" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/id_time" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="10sp" android:layout_alignParentTop="true" android:gravity="center"/> <com.example.yummylau.turingrobot.ui.CircularImage android:layout_below="@+id/id_time" android:layout_alignParentRight="true" android:id="@+id/id_iv" android:layout_width="50dp" android:layout_height="50dp" android:padding="10dp" /> <TextView android:layout_below="@+id/id_time" android:layout_marginTop="10dp" android:layout_marginRight="5dp" android:layout_marginLeft="50dp" android:layout_toLeftOf="@+id/id_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_tv" android:gravity="center_vertical" android:textSize="17sp" android:background="@drawable/aio_user_bg_nor_11" /> </RelativeLayout>
本人是使用android studio自带工具(强烈推荐)
上述时我在实现聊天气泡时用.9.png工具来实现。假设不是android studio IDE的能够自己的Android SDK\tools文件夹下双击draw9.path.bat来启动这个工具。
(1)上和左各划了1dp的长度。长度是用来拉伸的。假设你图片内内容太宽或者太高,则会依照你划的高度的内容来等量延伸。举个样例,比方说你的内容在竖直方向多出了300dp,那么图片就在话的左边的点(我们是1dp)自己主动添加300x1dp的长度来适配你的内容。
(2)右和下一般画得比較长。上述图片中看到两个矩形相重叠,重叠部分就是我们用户用来存放内容的。
点击“Show content”能够看到右側有内容填充的演示效果。
学会了.9.png的处理。再也不用操心图片变形了。而整个应用的UI设计和开发大致也就这么多。
调用图灵API获取数据json解析封装成Bean
而个人中心里面还有非常多功能:机器人设定、机器人调教等等。能够让自己的图灵机器人自主学习,回答指定问题等等。有兴趣的朋友能够继续研究。
package com.example.yummy.turingrobot; import android.os.AsyncTask; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; /** * 异步网络訪问类 * Created by yummy on 2015/7/12. */ public class MyAsync extends AsyncTask<String,Void,String>{ private String url; private HttpClient httpClient; private HttpGet httpGet; private HttpResponse httpResponse; private HttpEntity httpEntity; private InputStream inputStream; //使用回调的方法 private CallData data; public MyAsync(String url, CallData data) { this.url = url; this.data = http://www.mamicode.com/data;>(2)写一个数据接口,使得AsyncTask可以回调MainActivity组件进行显示。(一般也可以通过在AsyncTask的构造器中传进MainActivity引用来调用其组件)
package com.example.yummy.turingrobot; /** * 数据回调接口 * Created by yummy on 2015/7/12. */ public interface CallData { void getDataUrl(String data); }
@Override public void getDataUrl(String data) { System.out.println(data); lists.add(dataParse(data)); //通知改变 adapter.notifyDataSetChanged(); }
MyAsync myAsync = (MyAsync)new MyAsync("http://www.tuling123.com/openapi/api?" + "key=<自己的key>"+"发送内容",this).execute();
/** * 解析数据 * @param result * @return */ public Bean dataParse(String result){ try{ if(result.equals("亲。你还没有联网哦!")){ Bean listData = http://www.mamicode.com/new Bean(result, Bean.RECEIVER,getTime());>listview的优化显示
因为左右两边布局。传统的listview优化方法须要进行改进。一般我们使用viewholder来进行缓存,只是因为多布局适配。所以应该相应多布局缓存。
package com.example.yummy.turingrobot; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.yummylau.turingrobot.ui.CircularImage; import java.util.List; /** * 适配器 * Created by yummy on 2015/7/12. */ public class Adapter extends BaseAdapter{ private List<Bean> lists; private Context context; private LayoutInflater inflater; private ViewHolderLeft left; private ViewHolderRight right; //布局数目 private final int VIEW_TYPE = 2; //0为发送 private final int TYPE_0 = 0; //1为接受 private final int TYPE_1 = 1; public Adapter(List<Bean> lists,Context context) { this.lists = lists; this.context = context; } @Override public int getCount() { return lists.size(); } @Override public Object getItem(int position) { return lists.get(position); } @Override public long getItemId(int position) { return position; } /** * 说明下这种方法。每个view被调用的时候都会调用此方法。获取当前所须要的view样式 * @param position * @return */ @Override public int getItemViewType(int position) { return (lists.get(position).getFlag()== Bean.SEND)?TYPE_0:TYPE_1; } /** * 返回布局类型 * @return */ @Override public int getViewTypeCount() { return VIEW_TYPE; } @Override public View getView(int position, View convertView, ViewGroup parent) { left = null; right = null; inflater = LayoutInflater.from(context); int tpye = getItemViewType(position); //System.out.print(tpye+" ddd "); //初始化布局 if(convertView == null){ switch (tpye){ //0为发送 case TYPE_0: convertView = inflater.inflate(R.layout.rightitem,null); right = new ViewHolderRight(); right.rtextView = (TextView)convertView.findViewById(R.id.id_tv); right.rtime = (TextView)convertView.findViewById(R.id.id_time); right.riv = (CircularImage)convertView.findViewById(R.id.id_iv); convertView.setTag(right); break; //1为接受 case TYPE_1: convertView = inflater.inflate(R.layout.leftitem,null); left = new ViewHolderLeft(); left.ltextView = (TextView)convertView.findViewById(R.id.id_tv); left.ltime = (TextView)convertView.findViewById(R.id.id_time); left.liv = (CircularImage)convertView.findViewById(R.id.id_iv); convertView.setTag(left); break; } }else{ switch (tpye){ //0为发送 case TYPE_0: right = (ViewHolderRight)convertView.getTag(); break; //1为接收 case TYPE_1: left = (ViewHolderLeft)convertView.getTag(); break; } } /** * 设置每个布局的资源 */ switch (tpye){ //0为发送 case TYPE_0: right.rtextView.setText(lists.get(position).getContent()); right.rtime.setText(lists.get(position).getTime()); right.riv.setImageResource(R.drawable.youtouxiang); break; //1为接收 case TYPE_1: left.ltextView.setText(lists.get(position).getContent()); left.ltime.setText(lists.get(position).getTime()); left.liv.setImageResource(R.drawable.zuotouxiang); break; } return convertView; } //左側缓冲类 static class ViewHolderLeft{ TextView ltextView; TextView ltime; CircularImage liv; } //右側缓冲类 static class ViewHolderRight{ TextView rtextView; TextView rtime; CircularImage riv; } }
getViewTypeCount方法是返回我们布局的个数;
先推断convertView是否为空,空则初始化holder,不同则拿到相应标志的holder,最后适配数据进去就好了。
低门槛入门——图灵机器人开发