仿今日头条和qq侧滑和智慧北京的小项目 3

仿今日头条和QQ侧滑和智慧北京的小项目3

本项目图片素材均来自今日头条,QQ侧滑没有使用Android原生的NavigationDrawer,而使用的是第三方SlidingMenu,原因是这个控件暂时没有仔细研究(后期会研究并写demo),项目整体可以说是使用了一个Activity加多个Fragment,全部采用沉寂式。

前文摘要:仿今日头条和QQ侧滑和智慧北京的小项目2

TabPager(NewsPager新闻页面对应的11个子页面)

这里写图片描述

此页面相对比较复杂,所以单独用一篇blog来说明都处理了哪些逻辑

从网络上获取json数据

private void getDataFromNet() {HttpUtils httpUtils = new HttpUtils();httpUtils.send(HttpRequest.HttpMethod.GET, url, new RequestCallBack() {@Overridepublic void onSuccess(ResponseInfo responseInfo) {if (isRefresh) {isRefresh = false;listNews.onRefreshFinish(true);}Log.d(TAG, newsMenuTab.getTitle() + "数据请求成功" + responseInfo.result);//数据请求成功向本地保存一份CacheUtils.putString(mActivity, url, String.valueOf(responseInfo.result));//解析jsonresolutionJson((String) responseInfo.result);}@Overridepublic void onFailure(HttpException e, String s) {if (isRefresh) {listNews.onRefreshFinish(false);}Log.d(TAG, newsMenuTab.getTitle() + "数据请求失败");}});}
 

解析json数据

解析json数据分为若干部分,解析json、初始化数据、设置数据、处理和解析数据。

  • 解析json(javaBean在此不做赘述,获取json,直接生成即可)
private TopNewsBean topNewsJson(String result) {Gson gson = new Gson();TopNewsBean topNewsBean;topNewsBean = gson.fromJson(result, TopNewsBean.class);return topNewsBean;}
  • 初始化数据、设置数据
/*** 解析json数据** @param result*/private void resolutionJson(String result) {TopNewsBean topNewsBean = topNewsJson(result);if (!isLoadMore){//把解析json封装成一个方法这样看起来代码没那么乱topNewsList = topNewsBean.getData().getTopnews();moreUrl = topNewsBean.getData().getMore();if (TextUtils.isEmpty(moreUrl)) {moreUrl = null;}else {moreUrl = ConstantUtils.CONNECTURL+moreUrl;}//初始化顶部新闻的Viewpager数据//初始化Viewpager数据TopNewsTabAdapter topNewsTabAdapter = new TopNewsTabAdapter();
//        给ViewPager设置数据hvp.setAdapter(topNewsTabAdapter);hvp.setOnPageChangeListener(this);//初始化文字和点llPoint.removeAllViews();//因为访问网络读取缓存这个方法会被执行2此,所以需要要移除以前的viewView view = null;for (int i = 0; i < topNewsList.size(); i++) {view = new View(mActivity);view.setBackgroundResource(R.drawable.point_seclect);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(15, 15);if (i != 0) {params.leftMargin = 15;}view.setEnabled(false);view.setLayoutParams(params);llPoint.addView(view);}//初始化第一个点和文字firstDescription = 0;tvTopNewsDes.setText(topNewsList.get(firstDescription).getTitle());llPoint.getChildAt(firstDescription).setEnabled(true);//初始化listview数据newsItem = topNewsBean.getData().getNews();listNewsAdapter = new ListNewsAdapter();listNews.setAdapter(listNewsAdapter);// TODO: 16/5/28    给Viewpager设置自动滑动//因为该方法会执行2次,所以需要清空一次if (myHandle==null){myHandle = new MyHandle();}else {myHandle.removeCallbacksAndMessages(null);}myHandle.postDelayed(new MyRunnable(),4000);}else {isLoadMore = false;List moreNewsItem = topNewsBean.getData().getNews();newsItem.addAll(moreNewsItem);listNewsAdapter.notifyDataSetChanged();}}
  • 处理和解析数据

1、轮播图数据

class TopNewsTabAdapter extends PagerAdapter {@Overridepublic int getCount() {return topNewsList.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {ImageView imageView = new ImageView(mActivity);//给imageview设置事件//设置默认图片和背景拉伸imageView.setScaleType(ImageView.ScaleType.FIT_XY);imageView.setBackgroundResource(R.drawable.default_bg);bitmapUtils = new BitmapUtils(mActivity);// 配置默认图片的像素单位bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.ARGB_4444);//topimage的网络地址topNews = topNewsList.get(position);/*** container 下面的uri参数请求下来的图片, 设置给container来展示.* uri 图片的请求地址*/bitmapUtils.display(imageView, topNews.getTopimage());container.addView(imageView);return imageView;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}

2、列表listview新闻数据

class ListNewsAdapter extends BaseAdapter {@Overridepublic int getCount() {return newsItem.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;if (convertView == null) {convertView = View.inflate(mActivity, R.layout.listnews_item, null);viewHolder = new ViewHolder(convertView);convertView.setTag(viewHolder);}else {viewHolder = (ViewHolder) convertView.getTag();}TopNewsBean.DataBean.NewsBean newsBean = newsItem.get(position);viewHolder.tvListNews.setText(newsBean.getTitle());viewHolder.tvListDate.setText(newsBean.getPubdate());// 判断当前是否是已读的新闻String readableIDArray = CacheUtils.getString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, null);// TODO: 16/5/27if(!TextUtils.isEmpty(readableIDArray)&& readableIDArray.contains(newsBean.getId()+"")) {viewHolder.tvListNews.setTextColor(Color.GRAY);} else {viewHolder.tvListNews.setTextColor(Color.BLACK);}//设置默认图片viewHolder.ivListNews.setBackgroundResource(R.drawable.listnews_default_bg);bitmapUtils.display(viewHolder.ivListNews,newsBean.getListimage());return convertView;}class ViewHolder {@Bind(R.id.iv_list_news)public ImageView ivListNews;@Bind(R.id.tv_list_news)public TextView tvListNews;@Bind(R.id.tv_list_date)public TextView tvListDate;ViewHolder(View view) {ButterKnife.bind(this, view);}}}

viewpager轮播新闻页面逻辑

设置点和文字的自动切换、自动轮播

设置点和文字的自动切换

1、给Viewpager设置页面滑动监听

2、初始化点和文字描述控件

 //初始化文字和点llPoint.removeAllViews();//因为访问网络读取缓存这个方法会被执行2此,所以需要要移除以前的viewView view = null;for (int i = 0; i < topNewsList.size(); i++) {view = new View(mActivity);view.setBackgroundResource(R.drawable.point_seclect);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(15, 15);if (i != 0) {params.leftMargin = 15;}view.setEnabled(false);view.setLayoutParams(params);llPoint.addView(view);}//初始化第一个点和文字firstDescription = 0;tvTopNewsDes.setText(topNewsList.get(firstDescription).getTitle());llPoint.getChildAt(firstDescription).setEnabled(true);

3、主要实现onPageSelected方法

//Viewpager的滑动事件监听@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {//设置点的切换tvTopNewsDes.setText(topNewsList.get(position).getTitle());llPoint.getChildAt(firstDescription).setEnabled(false);llPoint.getChildAt(position).setEnabled(true);firstDescription = position;}@Overridepublic void onPageScrollStateChanged(int state) {}

自动轮播(通过Handle实现,定时任务)

为什么执行2次,第一次从缓存中读取数据,并处理数据,第二次从网络上获取数据,并处理数据。

// TODO: 16/5/28    给Viewpager设置自动滑动//因为该方法会执行2次,所以需要清空一次if (myHandle==null){myHandle = new MyHandle();}else {myHandle.removeCallbacksAndMessages(null);}myHandle.postDelayed(new MyRunnable(),4000);}else {isLoadMore = false;List moreNewsItem = topNewsBean.getData().getNews();newsItem.addAll(moreNewsItem);listNewsAdapter.notifyDataSetChanged();}//Handle
class MyHandle extends Handler{@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//用于处理消息int newCurrentItem = (hvp.getCurrentItem() + 1)%topNewsList.size();hvp.setCurrentItem(newCurrentItem);//消息处理完在重新发送,类似递归myHandle.postDelayed(new MyRunnable(),4000);}}//run方法
class MyRunnable implements Runnable{@Overridepublic void run() {//发一条空的消息myHandle.sendEmptyMessage(0);}}

列表新闻listview页面逻辑处理(自定义Listview)

下拉刷新、上拉加载

写一个类继承自listview,添加自定义头布局和尾布局,监听滑动事件等。
以下贴出关键代码。

下拉刷新部分

添加头布局

/*** 添加头布局*/private void initHeadView() {headView = View.inflate(getContext(), R.layout.refresh_headview, null);ButterKnife.bind(this, headView);this.addHeaderView(headView);//默认隐藏头布局headView.measure(0, 0);measuredHeight = headView.getMeasuredHeight();headView.setPadding(0, -measuredHeight, 0, 0);initAnimation();}

处理Listview的点击事件

/*** 重新onTouchEvent,处理点击事件* @param ev* @return*/@Overridepublic boolean onTouchEvent(MotionEvent ev) {int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN:if (downY == -1){downY = (int) ev.getY();}
//                downY = (int) ev.getY();break;case MotionEvent.ACTION_MOVE:if (downY == -1){downY = (int) ev.getY();}int moveY = (int) ev.getY();int diffY = moveY - downY;// 判断当前是否正在刷新中if(currentState == RELEASEREFRESH) {// 当前正在刷新中, 不执行下拉, 直接跳出break;}//如果是从上向下滑动,并且是第一个头布局,才进行下拉操作boolean isDisplay = isDisplaySecondHeaderView();if (diffY>0&&isDisplay) {int piddingTop = -measuredHeight+diffY;if (piddingTop >= 0 && currentState != RELEASEREFRESH){Log.i(TAG, "进入释放刷新状态");currentState = RELEASEREFRESH;refreshState();}else if (piddingTop<0  && currentState != DOWNREFRESH){Log.i(TAG, "进入下拉刷新");currentState = DOWNREFRESH;refreshState();}headView.setPadding(0,piddingTop,0,0);return true;}break;case MotionEvent.ACTION_UP:downY = -1;if(currentState == DOWNREFRESH) {// 当前是下拉刷新, 把头布局的隐藏headView.setPadding(0, -measuredHeight, 0, 0);} else if(currentState == RELEASEREFRESH) {// 当前是释放刷新, 进入到正在刷新中的状态currentState = INREFRESH;refreshState();headView.setPadding(0, 0, 0, 0);//                     调用用户的回调事件, 刷新数据if(mOnRefreshListener != null) {mOnRefreshListener.onPullDownRefresh();}}break;}return super.onTouchEvent(ev);//判断3种状态private void refreshState() {switch (currentState) {case DOWNREFRESH: //下拉刷新ivRefresh.startAnimation(downAnima);tvRefresh.setText("下拉刷新");break;case RELEASEREFRESH: //释放刷新ivRefresh.startAnimation(upAnima);tvRefresh.setText("松开刷新");break;case INREFRESH: //刷新中ivRefresh.clearAnimation();ivRefresh.setVisibility(View.INVISIBLE);pbBar.setVisibility(View.VISIBLE);tvRefresh.setText("正在刷新中..");break;}}

定义回调接口

public interface OnRefreshListener {/*** 当下拉刷新时触发此方法*/public void onPullDownRefresh();public void onLoadingMore();}

上拉加载更多部分


/*** 添加角布局*/private void initFooterView() {footView = View.inflate(getContext(), R.layout.listview_footerview, null);footView.measure(0,0);footViewHeight = footView.getMeasuredHeight();this.addFooterView(footView);footView.setPadding(0, -footViewHeight, 0, 0);this.setOnScrollListener(new OnScrollListener() {//当页面改变是调用@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// 当滚动停止时, 或者惯性滑动时, ListView最后一个显示的条目索引为getCount -1;if(scrollState == SCROLL_STATE_IDLE ||scrollState == SCROLL_STATE_FLING) {if(getLastVisiblePosition() == getCount() -1 && !isLoadingMore) {System.out.println("滚动到底部了");isLoadingMore  = true;footView.setPadding(0, 0, 0, 0);// 让ListView滚动到底部setSelection(getCount());// 调用使用者的回调事件if(mOnRefreshListener != null) {mOnRefreshListener.onLoadingMore();}}}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}});}

NewsDetailUI类(Listview页面item条目的事件处理)

image

点击listview条目进入一个新的页面,通过WebView展示一个web网页

listNews.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView parent, View view, int position, long id) {int newsposition = position - 2;newsBeanItem = newsItem.get(newsposition);// 先把已读新闻的id取出来String readableIDArray = CacheUtils.getString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, "");if(!readableIDArray.contains(newsBeanItem.getId()+"")) {String currentID = null;if(TextUtils.isEmpty(readableIDArray)) {currentID = newsBeanItem.getId() + ", ";} else {currentID = readableIDArray + newsBeanItem.getId() + ", ";}// 把这条新闻的id存储起来CacheUtils.putString(mActivity, READABLE_NEWS_ID_ARRAY_KEY, currentID);}listNewsAdapter.notifyDataSetChanged();Intent intent = new Intent(mActivity, NewsDetailUI.class);intent.putExtra("url", newsBeanItem.getUrl());intent.putExtra("title",newsBeanItem.getTitle());mActivity.startActivity(intent);}});

初始化数据

private void initData() {mIbFinish.setVisibility(View.VISIBLE);mIbTextSize.setVisibility(View.VISIBLE);mIbShare.setVisibility(View.VISIBLE);mTvTitle.setMaxWidth(600);mTvTitle.setMaxLines(1);mTvTitle.setEllipsize(TextUtils.TruncateAt.valueOf("END"));mTvTitle.setText(getIntent().getStringExtra("title"));String url = getIntent().getStringExtra("url");settings = mWebView.getSettings();
//        settings.setJavaScriptEnabled(true); // 启用javascript脚本
//        settings.setBuiltInZoomControls(true); // 启用界面上放大和缩小按钮
//        settings.setUseWideViewPort(true); // 启用双击放大, 双击缩小功能mWebView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageFinished(WebView view, String url) {mPbLoading.setVisibility(View.GONE);}});mWebView.loadUrl(url);}

设置字体大小

/*** 设置webView的字体大小*/private void setTextSize() {AlertDialog.Builder ab = new AlertDialog.Builder(this);ab.setTitle("选择字体大小");String[] item = new String[]{"超大号字体","大号字体","正常字体","小号字体","超小号字体"};ab.setSingleChoiceItems(item, currentSelectTextSize, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {tempCurrent = which;}});ab.setNeutralButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {currentSelectTextSize = tempCurrent;changeTextSize();}});ab.setPositiveButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});ab.show();}

share分享(第三方sdk使用在这里暂时不做介绍,根据官方文档一步一步就行了)

/*** 一键社会化分享*/private void mobShare() {ShareSDK.initSDK(this);OnekeyShare oks = new OnekeyShare();//关闭sso授权oks.disableSSOWhenAuthorize();// 分享时Notification的图标和文字  2.5.9以后的版本不调用此方法//oks.setNotification(R.drawable.ic_launcher, getString(R.string.app_name));// title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用oks.setTitle("智慧北京");// titleUrl是标题的网络链接,仅在人人网和QQ空间使用oks.setTitleUrl("http://sharesdk.cn");// text是分享文本,所有平台都需要这个字段oks.setText("我是分享文本");// imagePath是图片的本地路径,Linked-In以外的平台都支持此参数//oks.setImagePath("/sdcard/test.jpg");//确保SDcard下面存在此张图片// url仅在微信(包括好友和朋友圈)中使用oks.setUrl("http://sharesdk.cn");// comment是我对这条分享的评论,仅在人人网和QQ空间使用oks.setComment("我是测试评论文本");// site是分享此内容的网站名称,仅在QQ空间使用oks.setSite(getString(R.string.app_name));// siteUrl是分享此内容的网站地址,仅在QQ空间使用oks.setSiteUrl("http://sharesdk.cn");// 启动分享GUIoks.show(this);}

PhotosPager(组图页面的实现)

image

简单几步,获取数据,解析数据
初始化数据

@Overridepublic void initData() {bitmapUtils = new BitmapUtils(mActivity);bitmapUtils.configDefaultBitmapConfig(Bitmap.Config.ARGB_4444);url = ConstantUtils.PHOTOSURL;//先从缓存中读取数据String photosJsonData = CacheUtils.getString(mActivity, url, null);if (photosJsonData != null) {parserJsonData(photosJsonData);}//从网络上请求数据getDataFromNet();}private void getDataFromNet() {HttpUtils httpUtils = new HttpUtils();httpUtils.send(HttpRequest.HttpMethod.GET, url, new RequestCallBack() {@Overridepublic void onSuccess(ResponseInfo responseInfo) {//请求成功本地存一份json,解析json
//                Log.d(TAG, "onSuccess: "+responseInfo.result);String result = (String) responseInfo.result;parserJsonData(result);CacheUtils.putString(mActivity, url, result);}@Overridepublic void onFailure(HttpException e, String s) {Log.e(TAG, "onFailure: 组图数据请求失败。" + e);}});} 

解析数据

private void parserJsonData(String result) {PhotosBean photosBean = parserJson(result);//主要取得数据图片的url+titlephotoNews = photosBean.getData().getNews();//设置listview数据PhotoAdapter photoAdapter = new PhotoAdapter();llPhotos.setAdapter(photoAdapter);}private PhotosBean parserJson(String result) {Gson gson = new Gson();PhotosBean photosBean = gson.fromJson(result, PhotosBean.class);return photosBean;}class PhotoAdapter extends BaseAdapter {@Overridepublic int getCount() {return photoNews.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;if (convertView == null) {viewHolder =  new ViewHolder();convertView = View.inflate(mActivity, R.layout.photos_list_item, null);viewHolder.ivPhotoPhotos = (ImageView) convertView.findViewById(R.id.iv_photo_photos);viewHolder.tvTitlePhotos = (TextView) convertView.findViewById(R.id.tv_title_photos);convertView.setTag(viewHolder);}else {viewHolder = (ViewHolder) convertView.getTag();}PhotosBean.DataBean.NewsBean newsBean = photoNews.get(position);viewHolder.tvTitlePhotos.setText(newsBean.getTitle());//设置默认图片viewHolder.ivPhotoPhotos.setImageResource(R.drawable.default_bg);bitmapUtils.display(viewHolder.ivPhotoPhotos,newsBean.getListimage());return convertView;}public class ViewHolder {
//            @Bind(R.id.iv_photo_photos)public ImageView ivPhotoPhotos;
//            @Bind(R.id.tv_title_photos)public TextView tvTitlePhotos;}}

切换视图

 /*** 用于切换视图的方法* @param ib*/public void switchView(ImageButton ib) {//more没有切换是listvif (isSingleColumns) {llPhotos.setVisibility(View.VISIBLE);gvPhoto.setVisibility(View.GONE);llPhotos.setAdapter(new PhotoAdapter());isSingleColumns =false;ib.setImageResource(R.mipmap.icon_pic_list_type);}else {llPhotos.setVisibility(View.GONE);gvPhoto.setVisibility(View.VISIBLE);gvPhoto.setAdapter(new PhotoAdapter());isSingleColumns =true;ib.setImageResource(R.mipmap.icon_pic_grid_type);}}

至此,本小项目完成。其他页面暂不做实现,其处理逻辑参考“新闻中心”页面即可。

关于作者
- 个人主页:Hsia
- Email:xiaweifeng@live.cn
- 项目地址:https://github.com/swordman20/Zhbj


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章