您的位置:首页 > Web前端 > JavaScript

解析Json数据并通过Fragment填充到ViewPager中

2015-10-11 09:45 621 查看
昨天还有一个重要的知识点没有写,今天就整理出来写一篇博文吧。

昨天讲的最后一个知识点就是把网络解析的内容通过Fragment填充到ViewPager中。这和我们之前的一篇博文点击打开链接是比较类似的,

唯一的不同是我们需要解析出来数据来填充ViewPager,但是整体的思路都是使用Fragment来填充的。

再次明确一点,我怕自己忘了,所以又写一遍:对于使用Fragment来填充ViewPager的实现,我们自定义的Fragment所继承的Fragment

是v4包下的,还有就是MainActivity继承的是FragmentActivity。

好了,接下来我们看一下具体的实现步骤吧。

一、在activity_main.xml文件中声明一个ViewPager控件和一个LinearLayout控件

这个Linear控件是用来填充我们切换界面时的图标显示及变化的。

<LinearLayout 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"
android:padding="10dp"
android:orientation="vertical">

<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6" >
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="@android:color/holo_orange_light"
android:orientation="horizontal">

</LinearLayout>
</LinearLayout>
二、接下来是明确我们想要得到的数据并把它们封装到一个类中,然后得到该类的集合

①这里我们先贴一下所要解析的Json数据的格式吧



②在上图中,我们想要得到内层的“subject”和"photo"所对应的数据,所以这里我们把两者封装到了一个News类中:

package com.example.text_05_bean;

import java.io.Serializable;

public class News implements Serializable {

private String subject;
private String photo;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}

}
③接下来是解析网络数据并得到News对象的集合,这里我们定义了一个HttpUtils工具类:

package com.example.text_05_http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.example.text_05_bean.News;

public class HttpUtils {
// 得到解析出来的Json数据
public static String getJsonContent(String path) {
String result = "";
BufferedReader bufr = null;
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bufr = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = "";
while ((line = bufr.readLine()) != null) {
result += line;
}
} catch (Exception e) {

e.printStackTrace();
} finally {
try {
bufr.close();
} catch (IOException e) {

e.printStackTrace();
}
}
return result;
}

// 得到我们需要的存放News对象的集合
public static List<News> getNews(String path) {
List<News> list = new ArrayList<News>();
String json = getJsonContent(path);
try {
// 得到Json数据中最外层的对象
JSONObject obj = new JSONObject(json);
// 根据内层的变量名称和对象类型得到我们需要的数据
JSONArray arr = obj.getJSONObject("paramz").getJSONArray("tops");
for (int i = 0; i < arr.length(); i++) {
JSONObject obj2 = arr.getJSONObject(i);
News news = new News();
// 根据解析到的对象得到对应的值并设置到News对象的对应属性中
news.setSubject(obj2.getString("subject"));
news.setPhoto("http://litchiapi.jstv.com"
+ obj2.getString("photo"));
// 把News对象添加到list集合中
list.add(news);
}
} catch (JSONException e) {

e.printStackTrace();
}
return list;
}
}
三、然后是创建MyFragment类继承自v4包下的Fragment,并新建一个布局文件用来显示我们解析的内容

这里我们解析的是一段标题和一个图片,所以对于xml文件来说,一个TextView和ImageView就可以了。

①xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
android:id="@+id/tv_subject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="信息" />

<ImageView
android:id="@+id/im_photo"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_below="@id/tv_subject"
android:layout_marginTop="10dp"
android:src="@drawable/ic_launcher" />

</RelativeLayout>
②MyFragment类:

package com.example.text_05;

import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.text_05_bean.News;

public class MyFragment extends Fragment {

private Bitmap bitmap;
private ImageView iv;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, null);
TextView tv = (TextView) view.findViewById(R.id.tv_subject);
iv = (ImageView) view.findViewById(R.id.im_photo);
//得到传来的bundle对象并得到其携带的数据,就是News对象
Bundle bundle = getArguments();
News news = (News) bundle.getSerializable("news");
tv.setText(news.getSubject());
String path = news.getPhoto();
//执行加载图片的异步任务
new MyTask().execute(path);
return view;
}
//异步任务加载图片资源
class MyTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
} catch (Exception e) {

e.printStackTrace();
}
return bitmap;
}

@Override
protected void onPostExecute(Bitmap result) {

super.onPostExecute(result);
iv.setImageBitmap(bitmap);
}
}
}
四、最后一步了,也是比较难写但却又非常重要的对于ViewPager布局的填充了,

我们直接看代码吧,注释还是比较详细的。

package com.example.text_05;

import java.util.ArrayList;
import java.util.List;

import com.example.text_05_bean.News;
import com.example.text_05_http.HttpUtils;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

//继承自FragmentActivity
public class MainActivity extends FragmentActivity {

private String path = "http://litchiapi.jstv.com/api/getTops?limit=5&column=0&val=F467412B44B421716757A6B2D7635B4A";
private ViewPager viewPager;
// 定义存储Fragment的集合
private List<Fragment> fragments;
// 声明我们定义的Fragment的子类
private MyFragment fragment;
// 声明我们在activity_main.xml文件布局中定义的LinearLayou控件
private LinearLayout layout;
private List<News> list;
// 定义FragmentManager管理者
private FragmentManager fm;
// 定义存储圆点图标的集合
private ImageView[] icons;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
fragments = new ArrayList<Fragment>();
layout = (LinearLayout) findViewById(R.id.layout);
list = new ArrayList<News>();
// 获得Fragment管理者对象,对于使用Fragment填充ViewPager时,获得的管理者对象
// 是getSupportFragmentManager()
fm = getSupportFragmentManager();
// 启动异步任务
new MyTask().execute(path);
}

// 定义异步任务解析数据得到list集合
class MyTask extends AsyncTask<String, Void, List<News>> {
@Override
protected List<News> doInBackground(String... params) {
//调用HttpUtils中的方法得到list集合
list = HttpUtils.getNews(path);
return list;
}

@Override
protected void onPostExecute(List<News> result) {

super.onPostExecute(result);
// 根据解析出来的集合的长度创建MyFragment对象并把解析出来的数据依次添加到Fragment中
for (int i = 0; i < result.size(); i++) {
fragment = new MyFragment();
// 把我们解析出来的News对象放置在bundle中并传序列化给Fragment
// 这样该Fragment就可以得到集合中每个索引所对应的News对象
// 然后再添加到fragments集合中,这样集合中的Fragment就有数据存在了
// 并进而可以把在MyFragment得到并把数据填充到ViewPager中
Bundle bundle = new Bundle();
bundle.putSerializable("news", result.get(i));
fragment.setArguments(bundle);
// 把MyFragment对象添加到fragments集合中
fragments.add(fragment);
}
// 创建我们自定义的适配器对象,这里需要传一个Fragment管理者参数,在onCreate方法中我们已经得到了
MyAdapter adapter = new MyAdapter(fm);
viewPager.setAdapter(adapter);
// 设置ViewPager的监听事件,就是当我们切换ViewPager时改变对应圆点的状态
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
// 当选中页面的位置为arg0时
@Override
public void onPageSelected(int arg0) {
// 循环设置每一个圆点图标为icon01
for (int i = 0; i < icons.length; i++) {
icons[i].setImageResource(R.drawable.icon01);
}
// 设置arg0位置,就是我们页面所处位置的圆点图标为icon02
icons[arg0].setImageResource(R.drawable.icon02);
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}

@Override
public void onPageScrollStateChanged(int arg0) {
}
});
// 初始化圆点,根据解析出来的集合长度定义icons数组的长度
icons = new ImageView[result.size()];
for (int i = 0; i < icons.length; i++) {
// 把图片资源加载到icons数组中
icons[i] = new ImageView(MainActivity.this);
icons[i].setImageResource(R.drawable.icon01);
// 设置圆点的属性
icons[i].setMaxHeight(20);
icons[i].setAdjustViewBounds(true);
// 给圆点设置一个标记以实现在点击不同圆点时切换到不同的界面
icons[i].setTag(i);
icons[i].setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
// 切换到当前圆点对应的ViewPager
viewPager.setCurrentItem((Integer) v.getTag());
}
});
// 把圆点加入到LinearLayout布局控件中
layout.addView(icons[i]);
}
// 默认设置第1个图标为icon02
icons[0].setImageResource(R.drawable.icon02);
}
}

// 创建适配器,对于使用Fragment填充ViewPager,自定义适配器要继承FragmentPagerAdapter
class MyAdapter extends FragmentPagerAdapter {
// 其构造函数有一个FragmentManager对象
public MyAdapter(FragmentManager fm) {
super(fm);

}

// 得到arg0位置的Fragment以填充到Activity中
@Override
public Fragment getItem(int arg0) {

return fragments.get(arg0);
}

// fragments集合的总数,简单说就是切换页面的个数
@Override
public int getCount() {

return fragments.size();
}

}

}
好了,具体的实现就是这四个步骤了,接下来我们看一下运行结果吧:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: