Gson
Android-Universal-Image-Loader
android-async-http
dependencies {
compile 'org.apache.httpcomponents:httpcore:4.4.2'
}
package krelve.app.kuaihu; import android.app.Application; import android.content.Context; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator; import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.QueueProcessingType; import com.nostra13.universalimageloader.utils.StorageUtils; import java.io.File; /** * Created by wwjun.wang on 2015/8/11. */ public class Kpplication extends Application { @Override public void onCreate() { super.onCreate(); initImageLoader(getApplicationContext()); } private void initImageLoader(Context context) { File cacheDir = StorageUtils.getCacheDirectory(context); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( context).threadPoolSize(3) .threadPriority(Thread.NORM_PRIORITY - 2) .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) .denyCacheImageMultipleSizesInMemory() .diskCacheFileNameGenerator(new Md5FileNameGenerator()) .tasksProcessingOrder(QueueProcessingType.LIFO) .diskCache(new UnlimitedDiskCache(cacheDir)).writeDebugLogs() .build(); ImageLoader.getInstance().init(config); } }
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical"> android:id="@+id/iv_start" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:scaleType="fitXY" />
package krelve.app.kuaihu.activity; import android.app.Activity; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.Window; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.ImageView; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.BinaryHttpResponseHandler; import org.apache.http.Header; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import krelve.app.kuaihu.R; import krelve.app.kuaihu.util.Constant; import krelve.app.kuaihu.util.HttpUtils; /** * Created by wwjun.wang on 2015/8/11. */ public class SplashActivity extends Activity { private ImageView iv_start; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.splash); iv_start = (ImageView) findViewById(R.id.iv_start); initImage(); } private void initImage() { File dir = getFilesDir(); final File imgFile = new File(dir, "start.jpg"); if (imgFile.exists()) { iv_start.setImageBitmap(BitmapFactory.decodeFile(imgFile.getAbsolutePath())); } else { iv_start.setImageResource(R.mipmap.start); } final ScaleAnimation scaleAnim = new ScaleAnimation(1.0f, 1.2f, 1.0f, 1.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnim.setFillAfter(true); scaleAnim.setDuration(3000); scaleAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { HttpUtils.get(Constant.START, new AsyncHttpResponseHandler() { @Override public void onSuccess(int i, Header[] headers, byte[] bytes) { try { JSONObject jsonObject = new JSONObject(new String(bytes)); String url = jsonObject.getString("img"); HttpUtils.get(url, new BinaryHttpResponseHandler() { @Override public void onSuccess(int i, Header[] headers, byte[] bytes) { saveImage(imgFile, bytes); startActivity(); } @Override public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) { startActivity(); } }); } catch (JSONException e) { e.printStackTrace(); } } @Override public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) { startActivity(); } }); } @Override public void onAnimationRepeat(Animation animation) { } }); iv_start.startAnimation(scaleAnim); } private void startActivity() { Intent intent = new Intent(SplashActivity.this, MainActivity.class); startActivity(intent); overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); finish(); } public void saveImage(File file, byte[] bytes) { try { file.delete(); FileOutputStream fos = new FileOutputStream(file); fos.write(bytes); fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
在知乎日报的接口中,我们会看到这样一个接口:
http://news-at.zhihu.com/api/4/start-image/1080*1776
用来获取启动界面的图像,所以在启动时,要去获取最新的启动图像。
这里用到了android-http-async框架和UIM框架,在Module的build.gradle文件中添加:
还要记得在manifest文件中加权限:
这样基本就完成了一个启动页面,很简单。
3.主界面布局:
先来一个效果图:
可以看到,用到了Toolbar和DrawerLayout还有SwipeRefreshLayout。
布局文件
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/sr"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"
android:theme="@style/MyActionBar" />
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:name="krelve.app.kuaihu.fragment.MenuFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="left" />
可以看到Toolbar的位置在DrawerLayout的里面,如果想要侧滑的时候侧滑菜单显示在Toolbar的下面,只需让Toolbar的位置在DrawerLayout外面就行。
android:theme=ThemeOverlay.AppCompat.ActionBar
给我们的Toolbar引用这个style就达到了目的。
xml version="1.0" encoding="utf-8"?>关键点是ListView,这里要显示的数据我们要通过接口 http://news-at.zhihu.com/api/4/themes 来获取,为了简化网络操作,对android-http-async进行了及其简单的封装:xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="360dp" android:layout_height="match_parent" android:clickable="true" android:orientation="vertical"> android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_blue_dark" android:orientation="vertical" android:paddingBottom="10dp"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginTop="15dp" android:orientation="horizontal"> android:layout_width="36dp" android:layout_height="36dp" android:background="@drawable/ic_account_circle_white_24dp" /> android:layout_width="wrap_content" android:layout_height="36dp" android:layout_marginLeft="10dp" android:gravity="center_vertical" android:text="请登录" android:textColor="@android:color/white" android:textSize="18sp" /> android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="25dp" android:orientation="horizontal"> android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_weight="1" android:drawableLeft="@drawable/ic_star_white_24dp" android:gravity="center" android:text="我的收藏" android:textColor="@android:color/white" android:textSize="15sp" /> android:id="@+id/tv_download" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_weight="1" android:drawableLeft="@drawable/ic_file_download_white_24dp" android:gravity="center" android:text="离线下载" android:textColor="@android:color/white" android:textSize="15sp" /> android:id="@+id/tv_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFF0F0F0" android:paddingBottom="10dp" android:paddingLeft="80dp" android:paddingTop="10dp" android:text="首页" android:textColor="@android:color/holo_blue_dark" android:textSize="18sp" /> android:id="@+id/lv_item" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:divider="@android:color/transparent" android:scrollbars="none">
package krelve.app.kuaihu.util; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.ResponseHandlerInterface; /** * Created by wwjun.wang on 2015/8/11. */ public class HttpUtils { private static AsyncHttpClient client = new AsyncHttpClient(); public static void get(String url, ResponseHandlerInterface responseHandler) { client.get(Constant.BASEURL + url, responseHandler); } }
package krelve.app.kuaihu.fragment; import android.os.Bundle; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import com.loopj.android.http.JsonHttpResponseHandler; import org.apache.http.Header; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import krelve.app.kuaihu.R; import krelve.app.kuaihu.model.NewsListItem; import krelve.app.kuaihu.util.Constant; import krelve.app.kuaihu.util.HttpUtils; public class MenuFragment extends Fragment implements OnClickListener { private ListView lv_item; private TextView tv_download, tv_main; // private static String[] ITEMS = { "日常心理学", "用户推荐日报", "电影日报", "不许无聊", // "设计日报", "大公司日报", "财经日报", "互联网安全", "开始游戏", "音乐日报", "动漫日报", "体育日报" }; private Listitems; private Handler handler = new Handler(); @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState ) { View view = inflater.inflate(R.layout.menu, container, false); tv_download = (TextView) view.findViewById(R.id.tv_download); tv_download.setOnClickListener(this); tv_main = (TextView) view.findViewById(R.id.tv_main); tv_main.setOnClickListener(this); lv_item = (ListView) view.findViewById(R.id.lv_item); getItems(); return view; } private void getItems() { items = new ArrayList(); HttpUtils.get(Constant.THEMES, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { super.onSuccess(statusCode, headers, response); try { JSONArray itemsArray = response.getJSONArray("others"); for (int i = 0; i < itemsArray.length(); i++) { NewsListItem newsListItem = new NewsListItem(); JSONObject itemObject = itemsArray.getJSONObject(i); newsListItem.setTitle(itemObject.getString("name")); newsListItem.setId(itemObject.getString("id")); items.add(newsListItem); } handler.post(new Runnable() { @Override public void run() { lv_item.setAdapter(new NewsTypeAdapter()); } }); } catch (JSONException e) { e.printStackTrace(); } } }); } public class NewsTypeAdapter extends BaseAdapter { @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getActivity()).inflate( R.layout.menu_item, parent, false); } TextView tv_item = (TextView) convertView .findViewById(R.id.tv_item); tv_item.setText(items.get(position).getTitle()); return convertView; } } @Override public void onClick(View v) { } } }
package krelve.app.kuaihu.model; public class NewsListItem { private String title; private String id; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
xml version="1.0" encoding="utf-8"?>这样大概就完成了整个主界面的编写,如果有疏漏的地方,可以到github上看完整代码,我会根据进度实时上传。xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:paddingBottom="10dp" android:paddingLeft="15dp" android:paddingTop="10dp" android:text="新闻条目" android:textColor="#FF000000" android:textSize="16dp" />
package krelve.app.kuaihu.view; import android.content.Context; import android.os.Handler; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.LinearLayout; import android.widget.TextView; import com.nostra13.universalimageloader.core.ImageLoader; import java.util.ArrayList; import java.util.List; import krelve.app.kuaihu.Kpplication; import krelve.app.kuaihu.R; import krelve.app.kuaihu.model.Latest; public class Kanner extends FrameLayout implements OnClickListener { private ListTopStoriesEntity> topStoriesEntities; private ImageLoader mImageLoader; private List views; private Context context; private ViewPager vp; private boolean isAutoPlay; private int currentItem; private int delayTime; private LinearLayout ll_dot; private List iv_dots; private Handler handler = new Handler(); private OnItemClickListener mItemClickListener; public Kanner(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mImageLoader = ImageLoader.getInstance(); this.context = context; initView(); } private void initView() { views = new ArrayList (); iv_dots = new ArrayList (); delayTime = 2000; } public Kanner(Context context, AttributeSet attrs) { this(context, attrs, 0); } public Kanner(Context context) { this(context, null); } public void setTopEntities(List TopStoriesEntity> topEntities) { this.topStoriesEntities = topEntities; reset(); } private void reset() { views.clear(); initUI(); } private void initUI() { View view = LayoutInflater.from(context).inflate( R.layout.kanner_layout, this, true); vp = (ViewPager) view.findViewById(R.id.vp); ll_dot = (LinearLayout) view.findViewById(R.id.ll_dot); ll_dot.removeAllViews(); int len = topStoriesEntities.size(); for (int i = 0; i < len; i++) { ImageView iv_dot = new ImageView(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); params.leftMargin = 5; params.rightMargin = 5; ll_dot.addView(iv_dot, params); iv_dots.add(iv_dot); } for (int i = 0; i <= len + 1; i++) { View fm = LayoutInflater.from(context).inflate( R.layout.kanner_content_layout, null); ImageView iv = (ImageView) fm.findViewById(R.id.iv_title); TextView tv_title = (TextView) fm.findViewById(R.id.tv_title); iv.setScaleType(ScaleType.CENTER_CROP); iv.setBackgroundResource(R.drawable.loading1); if (i == 0) { mImageLoader.displayImage(topStoriesEntities.get(len - 1).getImage(), iv); tv_title.setText(topStoriesEntities.get(len - 1).getTitle()); } else if (i == len + 1) { mImageLoader.displayImage(topStoriesEntities.get(0).getImage(), iv); tv_title.setText(topStoriesEntities.get(0).getTitle()); } else { mImageLoader.displayImage(topStoriesEntities.get(i - 1).getImage(), iv); tv_title.setText(topStoriesEntities.get(i - 1).getTitle()); } fm.setOnClickListener(this); views.add(fm); } vp.setAdapter(new MyPagerAdapter()); vp.setFocusable(true); vp.setCurrentItem(1); currentItem = 1; vp.addOnPageChangeListener(new MyOnPageChangeListener()); startPlay(); } private void startPlay() { isAutoPlay = true; handler.postDelayed(task, 3000); } private final Runnable task = new Runnable() { @Override public void run() { if (isAutoPlay) { currentItem = currentItem % (topStoriesEntities.size() + 1) + 1; if (currentItem == 1) { vp.setCurrentItem(currentItem, false); handler.post(task); } else { vp.setCurrentItem(currentItem); handler.postDelayed(task, 5000); } } else { handler.postDelayed(task, 5000); } } }; class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { return views.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(views.get(position)); return views.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } class MyOnPageChangeListener implements OnPageChangeListener { @Override public void onPageScrollStateChanged(int arg0) { switch (arg0) { case 1: isAutoPlay = false; break; case 2: isAutoPlay = true; break; case 0: if (vp.getCurrentItem() == 0) { vp.setCurrentItem(topStoriesEntities.size(), false); } else if (vp.getCurrentItem() == topStoriesEntities.size() + 1) { vp.setCurrentItem(1, false); } currentItem = vp.getCurrentItem(); isAutoPlay = true; break; } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int arg0) { for (int i = 0; i < iv_dots.size(); i++) { if (i == arg0 - 1) { iv_dots.get(i).setImageResource(R.drawable.dot_focus); } else { iv_dots.get(i).setImageResource(R.drawable.dot_blur); } } } } public void setOnItemClickListener(OnItemClickListener mItemClickListener) { this.mItemClickListener = mItemClickListener; } public interface OnItemClickListener { public void click(Latest.TopStoriesEntity entity); } @Override public void onClick(View v) { if (mItemClickListener != null) { Latest.TopStoriesEntity entity = topStoriesEntities.get(vp.getCurrentItem() - 1); mItemClickListener.click(entity); } } }
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent" /> android:id="@+id/ll_dot" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:gravity="right" android:orientation="horizontal" android:padding="8dp">
xml version="1.0" encoding="utf-8"?>那接下来就是如何设置这个控件要显示的数据了:xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> android:id="@+id/iv_title" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" /> android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginBottom="25dp" android:padding="10dp" android:text="标题" android:textColor="@android:color/white" android:textSize="20sp" />
package krelve.app.kuaihu.fragment; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.ListView; import com.google.gson.Gson; import com.loopj.android.http.TextHttpResponseHandler; import org.apache.http.Header; import java.util.ArrayList; import java.util.List; import krelve.app.kuaihu.R; import krelve.app.kuaihu.activity.MainActivity; import krelve.app.kuaihu.adapter.NewsItemAdapter; import krelve.app.kuaihu.model.Latest; import krelve.app.kuaihu.util.Constant; import krelve.app.kuaihu.util.HttpUtils; import krelve.app.kuaihu.view.Kanner; /** * Created by wwjun.wang on 2015/8/12. */ public class MainFragment extends BaseFragment { private ListView lv_news; private Listitems; private Latest latest; private Kanner kanner; private Handler handler = new Handler(); @Override protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.main_news_layout, container, false); lv_news = (ListView) view.findViewById(R.id.lv_news); View header = inflater.inflate(R.layout.kanner, lv_news, false); kanner = (Kanner) header.findViewById(R.id.kanner); kanner.setOnItemClickListener(new Kanner.OnItemClickListener() { @Override public void click(Latest.TopStoriesEntity entity) { } }); lv_news.addHeaderView(header); lv_news.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (lv_news != null && lv_news.getChildCount() > 0) { boolean enable = (firstVisibleItem == 0) && (view.getChildAt(firstVisibleItem).getTop() == 0); ((MainActivity) mActivity).setSwipeRefreshEnable(enable); } } }); return view; } @Override protected void initData() { super.initData(); HttpUtils.get(Constant.LATESTNEWS, new TextHttpResponseHandler() { @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { } @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { Gson gson = new Gson(); latest = gson.fromJson(responseString, Latest.class); kanner.setTopEntities(latest.getTop_stories()); handler.post(new Runnable() { @Override public void run() { List storiesEntities = latest.getStories(); Latest.StoriesEntity topic = new Latest.StoriesEntity(); topic.setType(Constant.TOPIC); topic.setTitle("今日热闻"); storiesEntities.add(0, topic); lv_news.setAdapter(new NewsItemAdapter(mActivity, storiesEntities)); } }); } }); } }
package krelve.app.kuaihu.model; import java.util.List; /** * Created by wwjun.wang on 2015/8/12. */ public class Latest { /** * top_stories : [{"id":7048089,"title":"发生类似天津爆炸事故时,该如何自救?","ga_prefix":"081309","image":"http://pic4.zhimg.com/494dafbd64c141fd023d4e58b3343fcb.jpg","type":0},{"id":7047383,"title":"每卖一辆车亏 4000 美元,这事儿跟「iPhone 成本仅几百元」挺像","ga_prefix":"081307","image":"http://pic1.zhimg.com/40e0f21292df0e8512385f191e71ad14.jpg","type":0},{"id":7047795,"title":"央视说要干预男男性行为,具体是怎么干预法?","ga_prefix":"081310","image":"http://pic4.zhimg.com/89f0bca7d4ccf70bd747f3675adc18eb.jpg","type":0},{"id":7047071,"title":"美国人最爱买的车第一名是它,第二名是它,第三名,还是它\u2026\u2026","ga_prefix":"081307","image":"http://pic1.zhimg.com/9c00c482251e82fa8e0b957fa9ceb334.jpg","type":0},{"id":7046751,"title":"今晚的修破斯哒是 · 小李子","ga_prefix":"081219","image":"http://pic3.zhimg.com/bc5f63634d9c9832da8593ac64ebb7d6.jpg","type":0}] * stories : [{"id":7047795,"title":"央视说要干预男男性行为,具体是怎么干预法?","ga_prefix":"081310","images":["http://pic3.zhimg.com/fe27abc8f094510f2d3b4f3706108b56.jpg"],"type":0},{"id":7048089,"title":"发生类似天津爆炸事故时,该如何自救?","ga_prefix":"081309","images":["http://pic1.zhimg.com/eabb48a57948dc405429d0c0185c7950.jpg"],"type":0},{"id":7047188,"title":"分析了一下,发现这几个中国城市不光物价高,而且收入低","ga_prefix":"081308","images":["http://pic2.zhimg.com/7ce0dfe918b11069bc857421876e6609.jpg"],"type":0},{"id":7047383,"title":"每卖一辆车亏 4000 美元,这事儿跟「iPhone 成本仅几百元」挺像","ga_prefix":"081307","images":["http://pic2.zhimg.com/b8319323c8f8e3ec0ccc80d4745305a9.jpg"],"type":0},{"id":7047071,"title":"美国人最爱买的车第一名是它,第二名是它,第三名,还是它\u2026\u2026","ga_prefix":"081307","images":["http://pic2.zhimg.com/822b9ce452e8d48e6d32b83d4c1ea6e9.jpg"],"type":0},{"id":7047484,"title":"理论上就业率对工资很重要,但是在中国没这么回事","ga_prefix":"081307","images":["http://pic4.zhimg.com/d08952ed50050efdcee33203a4225ba3.jpg"],"type":0},{"id":7047181,"title":"瞎扯 · 如何正确地吐槽","ga_prefix":"081306","images":["http://pic4.zhimg.com/1dd6304067619318034671af9cf26803.jpg"],"type":0}] * date : 20150813 */ private List看到这个实体bean的时候是不是感觉很复杂,写的时候很不好写?top_stories; private List stories; private String date; public void setTop_stories(List top_stories) { this.top_stories = top_stories; } public void setStories(List stories) { this.stories = stories; } public void setDate(String date) { this.date = date; } public List getTop_stories() { return top_stories; } public List getStories() { return stories; } public String getDate() { return date; } public static class TopStoriesEntity { /** * id : 7048089 * title : 发生类似天津爆炸事故时,该如何自救? * ga_prefix : 081309 * image : http://pic4.zhimg.com/494dafbd64c141fd023d4e58b3343fcb.jpg * type : 0 */ private int id; private String title; private String ga_prefix; private String image; private int type; public void setId(int id) { this.id = id; } public void setTitle(String title) { this.title = title; } public void setGa_prefix(String ga_prefix) { this.ga_prefix = ga_prefix; } public void setImage(String image) { this.image = image; } public void setType(int type) { this.type = type; } public int getId() { return id; } public String getTitle() { return title; } public String getGa_prefix() { return ga_prefix; } public String getImage() { return image; } public int getType() { return type; } @Override public String toString() { return "TopStoriesEntity{" + "id=" + id + ", title='" + title + '\'' + ", ga_prefix='" + ga_prefix + '\'' + ", image='" + image + '\'' + ", type=" + type + '}'; } } public static class StoriesEntity { /** * id : 7047795 * title : 央视说要干预男男性行为,具体是怎么干预法? * ga_prefix : 081310 * images : ["http://pic3.zhimg.com/fe27abc8f094510f2d3b4f3706108b56.jpg"] * type : 0 */ private int id; private String title; private String ga_prefix; private List images; private int type; public void setId(int id) { this.id = id; } public void setTitle(String title) { this.title = title; } public void setGa_prefix(String ga_prefix) { this.ga_prefix = ga_prefix; } public void setImages(List images) { this.images = images; } public void setType(int type) { this.type = type; } public int getId() { return id; } public String getTitle() { return title; } public String getGa_prefix() { return ga_prefix; } public List getImages() { return images; } public int getType() { return type; } @Override public String toString() { return "StoriesEntity{" + "id=" + id + ", title='" + title + '\'' + ", ga_prefix='" + ga_prefix + '\'' + ", images=" + images + ", type=" + type + '}'; } } @Override public String toString() { return "Latest{" + "top_stories=" + top_stories + ", stories=" + stories + ", date='" + date + '\'' + '}'; } }
lv_news.setOnScrollListener(new AbsListView.OnScrollListener(){ @Override public void onScrollStateChanged(AbsListView view,int scrollState){ } @Override public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount){if(lv_news!=null&&lv_news.getChildCount()>0){boolean enable=(firstVisibleItem==0)&&(view.getChildAt(firstVisibleItem).getTop()==0); ((MainActivity)mActivity).setSwipeRefreshEnable(enable); } } });现在大概就实现了今日热闻的展示,那接下来还要实现下拉刷新和自动加载更多,以及其他内容页的展示,今天就写这么多,有关ListView中每一条内容的展示布局等可以在源码中看,最新内容已同步到github
还有自动刷新的逻辑实现(目前只实现了今日热闻的刷新):
然后就是今天的重点了,首先去实现侧滑菜单栏的点击事件:
其实就是按照点击的position来获取对应的id,然后发出请求,动态的用Fragment来展示。
这才是主角:
package krelve.app.kuaihu.fragment; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.google.gson.Gson; import com.loopj.android.http.TextHttpResponseHandler; import com.nostra13.universalimageloader.core.ImageLoader; import org.apache.http.Header; import java.util.ArrayList; import krelve.app.kuaihu.R; import krelve.app.kuaihu.activity.MainActivity; import krelve.app.kuaihu.adapter.NewsItemAdapter; import krelve.app.kuaihu.model.News; import krelve.app.kuaihu.util.Constant; import krelve.app.kuaihu.util.HttpUtils; /** * Created by wwjun.wang on 2015/8/14. */ @SuppressLint("ValidFragment") public class NewsFragment extends BaseFragment { private ImageLoader mImageLoader; private ListView lv_news; private ImageView iv_title; private TextView tv_title; private String urlId; private News news; public NewsFragment(String id) { urlId = id; } @Override protected View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.news_layout, container, false); mImageLoader = ImageLoader.getInstance(); lv_news = (ListView) view.findViewById(R.id.lv_news); View header = LayoutInflater.from(mActivity).inflate( R.layout.news_header, lv_news, false); iv_title = (ImageView) header.findViewById(R.id.iv_title); tv_title = (TextView) header.findViewById(R.id.tv_title); lv_news.addHeaderView(header); // lv_news.setOnItemClickListener(new AdapterView.OnItemClickListener() { // // @Override // public void onItemClick(AdapterView> parent, View view, // int position, long id) { // NewsItem newsItem = (NewsItem) parent.getAdapter().getItem( // position); // Intent intent = new Intent(getActivity(), // ThemeNewsContentActivity.class); // intent.putExtra("id", newsItem.getId()); // intent.putExtra("title", newsItem.getTitle()); // startActivity(intent); // } // }); lv_news.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (lv_news != null && lv_news.getChildCount() > 0) { boolean enable = (firstVisibleItem == 0) && (view.getChildAt(firstVisibleItem).getTop() == 0); ((MainActivity) mActivity).setSwipeRefreshEnable(enable); } } });return view; }@Override protected void initData(){super.initData(); HttpUtils.get(Constant.THEMENEWS+urlId,new TextHttpResponseHandler(){@Override public void onFailure(int statusCode,Header[]headers,String responseString,Throwable throwable){ }@Override public void onSuccess(int statusCode,Header[]headers,String responseString){ Gson gson=new Gson(); news=gson.fromJson(responseString,News.class); tv_title.setText(news.getDescription()); mImageLoader.displayImage(news.getImage(),iv_title); lv_news.setAdapter(new NewsItemAdapter(mActivity,news.getStories())); } }); } }在完成了 今日热闻 后,对上面的代码肯定不陌生,因为它们有着惊人的相似,上面用到的所有bean都是用GsonFormat自动生成的,不过由于有很多重复的地方,所以我把 StoriesEntity 抽取了出来。