上一篇讲了如何从网络上获取到我们需要的数据,这次讲如何将这些数据显示出来。(聚合数据网站免费的数据一天只能访问100次,在开发时不断的调式界面,这点次数根本不够用,于是我开了个会员,好贵呀)
先放效果图
实现这个功能我们需要用到的东西有这些:1、一个用于承载数据的listview布局2、一个用于显示子项数据的布局3、实体类4、适配器5、将前者协调起来的activity
第一部分:listview布局
效果图:
一片空白(懒得截了,因为这个listview中没有任何东西,所以是一片空白)
代码:
xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:divider="#F0F0F0" android:dividerHeight="33dp" android:id="@+id/lv_joke" android:layout_width="match_parent" android:layout_height="match_parent"> ListView>第二部分:显示一条数据的布局
效果图:
代码:
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:paddingLeft="20dp" android:paddingRight="15dp" android:paddingTop="10dp" android:lineSpacingMultiplier="1.5" android:id="@+id/tv_joke_content" android:textSize="17.0dp" android:text="跟女友晚饭后猜拳,输的洗碗,女友连输三盘,女友吼道:“你敢不出石头,晚上等着睡客厅!” 我哆嗦的出了石头,二货女友开心的出了剪刀。。。" android:layout_width="match_parent" android:layout_height="wrap_content" /> <RelativeLayout android:layout_marginTop="15dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_marginTop="8dp" android:id="@+id/tv_joke_time" android:text="本笑话更新于17:05" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/iv_joke_forward" android:layout_alignParentRight="true" android:src="@drawable/skip" android:layout_width="30dp" android:layout_height="30dp" /> RelativeLayout> LinearLayout>我们不能使用默认的文字排版,因为默认的文字排版不仅丑,而且还是密集恐怖症的克星,不信的话提前可以看看这张图
这样的界面无法让人愉悦,于是需要对文字进行排版,其中 android:lineSpacingMultiplier="1.5" 用于控制行距,左右两侧使用padding控制(这个控制内边距,外边距是margin),经过多次的测试,才做出了一个我自己感觉还能看的过去的页面
此外这个布局中还有更新时间和转发(分享?)功能,这次不做介绍
第三部分:实体类
代码:
package com.everyday.wei.everyday; /** * Created by wei on 2017/10/19. */ public class JokeData { private String content; private String time; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } }
第四部分:适配器
代码:
package com.everyday.wei.everyday; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.TextView; import java.util.List; /** * Created by wei on 2017/10/19. */ public class JokeAdapter extends BaseAdapter { //得到上下文对象 private Context mContext; //数据源 private List其实适配器都是大同小异的操作,无非就是设置数据源,然后在getView中将数据源中的数据一一显示在对应的界面中而已,傻瓜式操作,jokeDataList; private LinearLayout linearLayout; //JokeAdapter的构造函数,创建JokeAdapter的时候需要传入数据和上下文对象 public JokeAdapter(Context mContext, List jokeDataList) { this.mContext=mContext; this.jokeDataList=jokeDataList; } @Override public int getCount() { return jokeDataList.size(); } @Override public Object getItem(int position) { return jokeDataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater layoutInflater= LayoutInflater.from(mContext); linearLayout= (LinearLayout) layoutInflater.inflate(R.layout.item_of_joke,null); TextView tv_joke_content= (TextView) linearLayout.findViewById(R.id.tv_joke_content); // TextView tv_joke_time= (TextView) linearLayout.findViewById(R.id.tv_joke_time); tv_joke_content.setText(jokeDataList.get(position).getContent()); //tv_joke_time.setText(jokeDataList.get(position).getTime()); return linearLayout; } }
不过需要注意的是,这次虽说数据量小,但是为了追求效率,提升性能,我们还是应该对listview进行优化,这个下篇讲
第五部分:activity
代码:
package com.everyday.wei.everyday; import android.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; /** * Created by wei on 2017/10/10. */ public class Joke extends Fragment implements TransmitHttpData{ private GetHttpData getHttpData; private JokeAdapter jokeAdapter; private List这部分的重点是解析json数据,先看一下网站给我们返回的数据jokeDataList; private JokeData jokeData; private ListView lv_joke; private View view; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view=inflater.inflate(R.layout.tab_joke,null); //将数组初始化 jokeDataList=new ArrayList<>(); return view; } @Override public void onStart() { Log.d("joke", "joke的onStart执行了 "); super.onStart(); lv_joke= (ListView) getActivity().findViewById(R.id.lv_joke); getHttpData= (GetHttpData) new GetHttpData("http://v.juhe.cn/joke/randJoke.php?key=60fbc4de5e9c94872a10268487583390",this).execute(); jokeAdapter =new JokeAdapter(view.getContext(),jokeDataList); lv_joke.setAdapter(jokeAdapter); } @Override public void GetData(String data) { Log.d("Joke", "从Joke中获取的数据是"+data); try { ParseJson(data); } catch (JSONException e) { e.printStackTrace(); } } public void ParseJson(String json) throws JSONException { //先得到json数据中的json数组 JSONObject obj1=new JSONObject(json); JSONArray result=obj1.getJSONArray("result"); //Log.d("joke", "result的值是 "+result); //其次对json中我们需要的正文进行提取 for (int i=0;i jokeData=new JokeData(); //得到笑话正文 String content=result.getString(i); JSONObject obj2=new JSONObject(content); String content1=obj2.getString("content"); //将目标信息放入实体类 jokeData.setContent(content1); //存入集合 jokeDataList.add(jokeData); //当数据发生改变时 改变listview的界面 jokeAdapter.notifyDataSetChanged(); //long unixtime=obj2.getLong("unixtime"); //Log.d("Joke", "content: "+content1+"/n unixtime:"+unixtime); //Log.d("Joke", "content: "+content); } } }
可以看到,这是一个包含数据的json,而我们需要的就是这个数组,所以解析思路如下,先获得数组,在从数组中获得我们需要的数据使用for循环来将这些数据一个一个解析出来,然后放在集合中。至此,这部分任务完成
反思与总结:
1、仔细思考一下,这个程序每次只显示固定的几条数据,那么如果用户看完了,该如何刷新了,我们没用工具去实现下拉刷新(以后做),那么这个程序无法自己刷新了吗?
gif图移动速度太快,可能大家没有看清,实际上,gif图中两次显示的数据其实是不一样的,为啥呢
在第一篇中我们使用replace来加载fragment,而replace加载的方式是:清除该区域原来的东西,重新加载一次fragment,说简单点就是,
使用replace,fragment的生命周期会重新进行一次,也就是说,刷新每日笑话中的数据,需要你切换选项卡一次,再切换回来,数据就会刷新
当然,这样做显然不是人性化的,虽然我们是小项目,但是也要人性化,所以这个功能(上拉刷新)以后添上
2、做这个我花的时间最多的不是写代码,而是调试布局,虽然是程序员,但也不可以不修边幅,一个用户对一个程序的评价往往界面占了很大的成分
如何让界面赏心悦目也是一个很深奥的课题,至少我的审美观就不行。。
3、csdn的排版我总是搞不懂,不知道是按照什么规则排的,每次该换行的不换,不该换行的换,很恼火,这样很影响阅读
4、下次再见,下次写的是转发(分享)功能,时间戳的转换,或许还有下拉刷新(可能性10%)