android124 zhihuibeijing 新闻中心-新闻 -北京页签 下拉刷新
缓存工具类:以url为key,json数据为value,
package com.itheima.zhbj52.utils; import com.itheima.zhbj52.global.GlobalContants; import android.content.Context;
import android.text.TextUtils; /**
* 缓存工具类
*/
public class CacheUtils { /**
* 设置缓存 key 是url, value是json(服务器返回的数据),图片BitmapUtils已经跟我们做了缓存。
*/
public static void setCache(String key, String value, Context ctx) {
PrefUtils.setString(ctx, key, value);
//可以将缓存放在文件中, 文件名就是Md5(url), 文件内容是json
} // 设置缓存
//CacheUtils.setCache(GlobalContants.CATEGORIES_URL,result, mActivity);
//读取缓存
//String cache = CacheUtils.getCache(GlobalContants.CATEGORIES_URL,mActivity);
/*
String cache = CacheUtils.getCache(GlobalContants.CATEGORIES_URL,mActivity);
if (!TextUtils.isEmpty(cache)) {// 如果缓存存在,直接解析数据, 无需访问网路。后面还是要访问网络,这里使用缓存只是让用户不去急,后面还是会更新的。
parseData(cache);
}
getDataFromServer();// 不管有没有缓存, 都获取最新数据, 保证数据最新
*/
/**
* 获取缓存 key 是url
*/
public static String getCache(String key, Context ctx) {
return PrefUtils.getString(ctx, key, null);
}
}
主页面:
package com.itheima.zhbj52.base; import java.util.ArrayList; import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
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.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import android.widget.Toast; import com.google.gson.Gson;
import com.itheima.zhbj52.NewsDetailActivity;
import com.itheima.zhbj52.R;
import com.itheima.zhbj52.domain.NewsData.NewsTabData;
import com.itheima.zhbj52.domain.TabData;
import com.itheima.zhbj52.domain.TabData.TabNewsData;
import com.itheima.zhbj52.domain.TabData.TopNewsData;
import com.itheima.zhbj52.global.GlobalContants;
import com.itheima.zhbj52.utils.CacheUtils;
import com.itheima.zhbj52.utils.PrefUtils;
import com.itheima.zhbj52.view.RefreshListView;
import com.itheima.zhbj52.view.RefreshListView.OnRefreshListener;
import com.lidroid.xutils.BitmapUtils;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.viewpagerindicator.CirclePageIndicator; /**
* 新闻中心-新闻-北京 页签详情页
*/
public class TabDetailPager extends BaseMenuDetailPager implements OnPageChangeListener { NewsTabData mTabData;
private TextView tvText; private String mUrl;
private TabData mTabDetailData; @ViewInject(R.id.vp_news)
private ViewPager mViewPager; @ViewInject(R.id.tv_title)
private TextView tvTitle;// 头条新闻的标题 private ArrayList<TopNewsData> mTopNewsList;// 头条新闻数据集合 @ViewInject(R.id.indicator)
private CirclePageIndicator mIndicator;// 头条新闻位置指示器(4个黑色的圆点) @ViewInject(R.id.lv_list)
private RefreshListView lvList;// 新闻列表 private ArrayList<TabNewsData> mNewsList; // 新闻数据集合
private NewsAdapter mNewsAdapter;
private String mMoreUrl;// 更多页面的地址 private Handler mHandler; public TabDetailPager(Activity activity, NewsTabData newsTabData) {
super(activity);
mTabData = newsTabData;
mUrl = GlobalContants.SERVER_URL + mTabData.url;
} @Override
public View initViews() {
View view = View.inflate(mActivity, R.layout.tab_detail_pager, null);
/*tab_detail_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.itheima.zhbj52.view.RefreshListView
android:id="@+id/lv_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:cacheColorHint="#fff"
android:layout_weight="1" >
</com.itheima.zhbj52.view.RefreshListView>
</LinearLayout>*/
// 加载头布局
View headerView = View.inflate(mActivity, R.layout.list_header_topnews,null);
//list_header_topnews.xml
/*<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.itheima.zhbj52.view.TopNewsViewPager
android:id="@+id/vp_news"
android:layout_width="match_parent"
android:layout_height="200dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#a000"
android:padding="3dp" >
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:textSize="16sp" />
<com.viewpagerindicator.CirclePageIndicator
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="10dip"
app:fillColor="#f00"
app:pageColor="@android:color/darker_gray"
app:radius="3dp"
app:strokeWidth="0dp" />
</RelativeLayout>
</RelativeLayout>*/ ViewUtils.inject(this, view);
ViewUtils.inject(this, headerView); // 将头条新闻以头布局的形式加给listview
lvList.addHeaderView(headerView);
// 设置下拉刷新监听
lvList.setOnRefreshListener(new OnRefreshListener() {//自定义监听器
@Override
public void onRefresh() {
getDataFromServer();
}
@Override
public void onLoadMore() {
if (mMoreUrl != null) {
getMoreDataFromServer();
} else {
Toast.makeText(mActivity, "最后一页了", Toast.LENGTH_SHORT)
.show();
lvList.onRefreshComplete(false);// 收起加载更多的布局
}
}
}); //这里只是方法的调用
lvList.setOnItemClickListener(new OnItemClickListener() {//执行的是RefreshListView的setOnItemClickListener()方法。 @Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
System.out.println("被点击:" + position);
// 35311,34221,34234,34342
// 在本地记录已读状态,将已读新闻的id保存进SharedPreferences(config.xml文件里面),
String ids = PrefUtils.getString(mActivity, "read_ids", "");
/*public static String getString(Context ctx, String key, String defaultValue) {
SharedPreferences sp = ctx.getSharedPreferences("config",
Context.MODE_PRIVATE);
return sp.getString(key, defaultValue);
}*/
String readId = mNewsList.get(position).id;
if (!ids.contains(readId)) {//防止重复点击会有重复。
ids = ids + readId + ",";
PrefUtils.setString(mActivity, "read_ids", ids);
/*public static void setString(Context ctx, String key, String value) {
SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
Context.MODE_PRIVATE);
sp.edit().putString(key, value).commit();
}*/
} //mNewsAdapter.notifyDataSetChanged();调用Adapter实现刷新,这里会调用Adapter的getView()方法,这个方法会执行getView()方法很多次。
changeReadState(view);// 实现局部界面刷新, 这个view就是被点击的item布局对象(点击的某一行),不去刷新所有的listView. // 跳转新闻详情页
Intent intent = new Intent();
intent.setClass(mActivity, NewsDetailActivity.class);
intent.putExtra("url", mNewsList.get(position).url);
mActivity.startActivity(intent);
}
}); return view;
} /**
* 改变已读新闻的颜色
*/
private void changeReadState(View view) {
TextView tvTitle = (TextView) view.findViewById(R.id.tv_title);
tvTitle.setTextColor(Color.GRAY);
} @Override
public void initData() {
String cache = CacheUtils.getCache(mUrl, mActivity);//mUrl是key,
if (!TextUtils.isEmpty(cache)) {
parseData(cache, false);
}
getDataFromServer();
} private void getDataFromServer() {
HttpUtils utils = new HttpUtils();
utils.send(HttpMethod.GET, mUrl, new RequestCallBack<String>() { @Override
public void onSuccess(ResponseInfo<String> responseInfo) {
String result = (String) responseInfo.result;
System.out.println("页签详情页返回结果:" + result); parseData(result, false); lvList.onRefreshComplete(true);//lvList就是RefreshListView对象 // 设置缓存
CacheUtils.setCache(mUrl, result, mActivity);
} @Override
public void onFailure(HttpException error, String msg) {
Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
error.printStackTrace(); lvList.onRefreshComplete(false);
}
});
} /**
* 加载下一页数据
*/
private void getMoreDataFromServer() {
HttpUtils utils = new HttpUtils();
utils.send(HttpMethod.GET, mMoreUrl, new RequestCallBack<String>() { @Override
public void onSuccess(ResponseInfo<String> responseInfo) {
String result = (String) responseInfo.result; parseData(result, true); lvList.onRefreshComplete(true);
} @Override
public void onFailure(HttpException error, String msg) {
Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();
error.printStackTrace();
lvList.onRefreshComplete(false);
}
});
} protected void parseData(String result, boolean isMore) {
Gson gson = new Gson();
mTabDetailData = gson.fromJson(result, TabData.class);
System.out.println("页签详情解析:" + mTabDetailData); // 处理下一页链接
String more = mTabDetailData.data.more;
if (!TextUtils.isEmpty(more)) {
mMoreUrl = GlobalContants.SERVER_URL + more;
} else {
mMoreUrl = null;
} if (!isMore) {
mTopNewsList = mTabDetailData.data.topnews; mNewsList = mTabDetailData.data.news; if (mTopNewsList != null) {
mViewPager.setAdapter(new TopNewsAdapter());
mIndicator.setViewPager(mViewPager);
mIndicator.setSnap(true);// 支持快照显示
mIndicator.setOnPageChangeListener(this); mIndicator.onPageSelected(0);// 让指示器重新定位到第一个点 tvTitle.setText(mTopNewsList.get(0).title);
} if (mNewsList != null) {
mNewsAdapter = new NewsAdapter();
lvList.setAdapter(mNewsAdapter);
} // 自动轮播条显示
if (mHandler == null) {//这里handler只能创建一个,如果创建了多个则多个handler会都发消息来轮播。
mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
int currentItem = mViewPager.getCurrentItem();
if (currentItem < mTopNewsList.size() - 1) {
currentItem++;
} else {
currentItem = 0;
}
mViewPager.setCurrentItem(currentItem);// 切换到下一个页面
mHandler.sendEmptyMessageDelayed(0, 3000);// 继续延时3秒发消息,
// 形成循环
};
};
mHandler.sendEmptyMessageDelayed(0, 3000);// 延时3秒后第一次轮播开始。
} } else {// 如果是加载下一页,需要将数据追加给原来的集合
ArrayList<TabNewsData> news = mTabDetailData.data.news;
mNewsList.addAll(news);
mNewsAdapter.notifyDataSetChanged();
}
} /**
* 头条新闻适配器
*/
class TopNewsAdapter extends PagerAdapter { private BitmapUtils utils; public TopNewsAdapter() {
utils = new BitmapUtils(mActivity);
utils.configDefaultLoadingImage(R.drawable.topnews_item_default);// 设置默认图片
} @Override
public int getCount() {
return mTabDetailData.data.topnews.size();
} @Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView image = new ImageView(mActivity);
image.setScaleType(ScaleType.FIT_XY);// 基于控件大小填充图片 TopNewsData topNewsData = mTopNewsList.get(position);
utils.display(image, topNewsData.topimage);// 传递imagView对象和图片地址 container.addView(image); image.setOnTouchListener(new TopNewsTouchListener());//设置触摸监听 return image;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
} /**
* 头条新闻的触摸监听
*/
class TopNewsTouchListener implements OnTouchListener { @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("按下");
mHandler.removeCallbacksAndMessages(null);// 删除Handler中的所有消息
// mHandler.postDelayed(new Runnable() {//mHandler延时去执行某个操作
// @Override
// public void run() {}
// }, 3000);
break;
case MotionEvent.ACTION_CANCEL://按下又滑动了,按下和抬起就无效了。
System.out.println("事件取消");
mHandler.sendEmptyMessageDelayed(0, 3000);
break;
case MotionEvent.ACTION_UP:
System.out.println("抬起");
mHandler.sendEmptyMessageDelayed(0, 3000);
break; default:
break;
} return true;
} } /**
* 新闻列表的适配器
*/
class NewsAdapter extends BaseAdapter { private BitmapUtils utils; public NewsAdapter() {
utils = new BitmapUtils(mActivity);
utils.configDefaultLoadingImage(R.drawable.pic_item_list_default);//默认图片
} @Override
public int getCount() {
return mNewsList.size();
} @Override
public TabNewsData getItem(int position) {
return mNewsList.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(mActivity, R.layout.list_news_item,
null);
/*<?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="wrap_content"
android:padding="10dp"
>
<ImageView
android:id="@+id/iv_pic"
android:layout_width="110dp"
android:layout_height="70dp"
android:scaleType="fitXY"
android:padding="1dp"
android:background="@android:color/darker_gray"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/image_demo" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/iv_pic"
android:text="新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题"
android:textColor="#000"
android:maxLines="2"
android:ellipsize="end"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tv_title"
android:text="2015-03-16 16:20"
android:layout_alignBottom="@id/iv_pic"
android:textColor="@android:color/darker_gray"
android:textSize="16sp" />
</RelativeLayout>*/
holder = new ViewHolder();
holder.ivPic = (ImageView) convertView.findViewById(R.id.iv_pic);
holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
holder.tvDate = (TextView) convertView.findViewById(R.id.tv_date);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
} TabNewsData item = getItem(position); holder.tvTitle.setText(item.title);
holder.tvDate.setText(item.pubdate); utils.display(holder.ivPic, item.listimage); String ids = PrefUtils.getString(mActivity, "read_ids", "");
if (ids.contains(getItem(position).id)) {//如果是已读则把新闻的文字颜色改为灰色。
holder.tvTitle.setTextColor(Color.GRAY);
} else {
holder.tvTitle.setTextColor(Color.BLACK);
} return convertView;
} } static class ViewHolder {
public TextView tvTitle;
public TextView tvDate;
public ImageView ivPic;
} @Override
public void onPageScrollStateChanged(int arg0) { } @Override
public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override
public void onPageSelected(int arg0) {
TopNewsData topNewsData = mTopNewsList.get(arg0);
tvTitle.setText(topNewsData.title);
}
}
上拉和下拉刷新:
package com.itheima.zhbj52.view; import java.text.SimpleDateFormat;
import java.util.Date; import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView; import com.itheima.zhbj52.R; /**
* 下拉刷新的ListView
*/
public class RefreshListView extends ListView implements OnScrollListener,
android.widget.AdapterView.OnItemClickListener { //3中状态
private static final int STATE_PULL_REFRESH = 0;// 下拉刷新
private static final int STATE_RELEASE_REFRESH = 1;// 松开刷新
private static final int STATE_REFRESHING = 2;// 正在刷新
private int mCurrrentState = STATE_PULL_REFRESH;// 当前状态 private View mHeaderView;
private int startY = -1;// 滑动起点的y坐标
private int mHeaderViewHeight; private TextView tvTitle;
private TextView tvTime;
private ImageView ivArrow;
private ProgressBar pbProgress;
private RotateAnimation animUp;
private RotateAnimation animDown; public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initHeaderView();
initFooterView();
} public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderView();
initFooterView();
} public RefreshListView(Context context) {
super(context);
initHeaderView();
initFooterView();
} /**
* 初始化头布局
*/
private void initHeaderView() {
mHeaderView = View.inflate(getContext(), R.layout.refresh_header, null);
this.addHeaderView(mHeaderView); tvTitle = (TextView) mHeaderView.findViewById(R.id.tv_title);
tvTime = (TextView) mHeaderView.findViewById(R.id.tv_time);
ivArrow = (ImageView) mHeaderView.findViewById(R.id.iv_arr);
pbProgress = (ProgressBar) mHeaderView.findViewById(R.id.pb_progress); mHeaderView.measure(0, 0);
mHeaderViewHeight = mHeaderView.getMeasuredHeight(); mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏头布局 initArrowAnim(); tvTime.setText("最后刷新时间:" + getCurrentTime());
} /*
* 初始化脚布局
*/
private void initFooterView() {
mFooterView = View.inflate(getContext(),R.layout.refresh_listview_footer, null);
this.addFooterView(mFooterView); mFooterView.measure(0, 0);
mFooterViewHeight = mFooterView.getMeasuredHeight(); mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏 this.setOnScrollListener(this);
} @Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
if (startY == -1) {// 确保startY有效
startY = (int) ev.getRawY();
}
if (mCurrrentState == STATE_REFRESHING) {// 正在刷新时不做处理
break;
}
int endY = (int) ev.getRawY();
int dy = endY - startY;// 手指移动的便宜量。 if (dy > 0 && getFirstVisiblePosition() == 0) {// 只有下拉并且当前是第一个item,才允许下拉,已经滑倒列表下面去了,再向下拉刷新是不出来的。
int padding = dy - mHeaderViewHeight;// 计算padding,padding是下拉刷新的顶部距离屏幕可见部分的距离。
mHeaderView.setPadding(0, padding, 0, 0);// 设置当前padding if (padding > 0 && mCurrrentState != STATE_RELEASE_REFRESH) {// 状态改为松开刷新
mCurrrentState = STATE_RELEASE_REFRESH;
refreshState(); //padding < 0则下拉刷新控件在屏幕里面,padding > 0则下拉刷新控件在屏幕外面。
} else if (padding < 0 && mCurrrentState != STATE_PULL_REFRESH) {// 改为下拉刷新状态
mCurrrentState = STATE_PULL_REFRESH;
refreshState();
} return true;
}
break;
case MotionEvent.ACTION_UP:
startY = -1;// 重置 if (mCurrrentState == STATE_RELEASE_REFRESH) {
mCurrrentState = STATE_REFRESHING;// 正在刷新
mHeaderView.setPadding(0, 0, 0, 0);// 显示
refreshState();
} else if (mCurrrentState == STATE_PULL_REFRESH) {
mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏
} break; default:
break;
}
return super.onTouchEvent(ev);
} /**
* 刷新下拉控件的布局
*/
private void refreshState() {
switch (mCurrrentState) {
case STATE_PULL_REFRESH:
tvTitle.setText("下拉刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animDown);
break;
case STATE_RELEASE_REFRESH:
tvTitle.setText("松开刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animUp);
break;
case STATE_REFRESHING:
tvTitle.setText("正在刷新...");
ivArrow.clearAnimation();// 必须先清除动画,才能隐藏
ivArrow.setVisibility(View.INVISIBLE);
pbProgress.setVisibility(View.VISIBLE); if (mListener != null) {
mListener.onRefresh();
}
break; default:
break;
}
} /**
* 初始化箭头动画
*/
private void initArrowAnim() {
// 箭头向上动画
animUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, //0到-180度
Animation.RELATIVE_TO_SELF, 0.5f);
animUp.setDuration(200);
animUp.setFillAfter(true); // 箭头向下动画
animDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, //-180到0度
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animDown.setDuration(200);
animDown.setFillAfter(true); } OnRefreshListener mListener;
private View mFooterView;
private int mFooterViewHeight;
public void setOnRefreshListener(OnRefreshListener listener) {
mListener = listener;
}
public interface OnRefreshListener {
public void onRefresh();
public void onLoadMore();// 加载下一页数据
} /*
* 收起下拉刷新的控件
*/
public void onRefreshComplete(boolean success) {
if (isLoadingMore) {// 正在加载更多...
mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏脚布局
isLoadingMore = false;
} else {
mCurrrentState = STATE_PULL_REFRESH;
tvTitle.setText("下拉刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE); mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏 if (success) {
tvTime.setText("最后刷新时间:" + getCurrentTime());
}
}
} /**
* 获取当前时间
*/
public String getCurrentTime() {
//HH为24小时制,hh为12小时制,MM大写一月份从1开始,mm小写一月份从0开始
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
} private boolean isLoadingMore; //ListView的监听器
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE
|| scrollState == SCROLL_STATE_FLING) { if (getLastVisiblePosition() == getCount() - 1 && !isLoadingMore) {// 滑动到最后
System.out.println("到底了.....");
mFooterView.setPadding(0, 0, 0, 0);// 显示
setSelection(getCount() - 1);// listview的方法改变listview显示位置。getCount()是listview的方法。 isLoadingMore = true;//防止多次滑动此方法执行多次。 if (mListener != null) {
mListener.onLoadMore();
}
}
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) { } OnItemClickListener mItemClickListener; @Override//ListView的方法
public void setOnItemClickListener(
android.widget.AdapterView.OnItemClickListener listener) {
super.setOnItemClickListener(this);//因为传的是this,所以走到下面的onItemClick()方法。 mItemClickListener = listener;//TabDetailPager传进来的OnItemClickListener
} @Override//响应setOnItemClickListener事件
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
if (mItemClickListener != null) {
//再去执行TabDetailPager里面的onItemClick()方法
mItemClickListener.onItemClick(parent, view, position- getHeaderViewsCount(), id);//getHeaderViewsCount()获取头结点的数量,只有减去了头结点的数量才能获取点击的是第几个列表。
}
} }
刷新头:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp" > <ImageView
android:id="@+id/iv_arr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/common_listview_headview_red_arrow" /> <ProgressBar
android:id="@+id/pb_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/custom_progress" 自定义圆环
<!--
custom_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" 动画
android:fromDegrees="0"
android:toDegrees="360" 动画是0度到360度
android:pivotX="50%" 旋转中心点
android:pivotY="50%"
>
<shape 形状
android:innerRadius="12dp" 内半径
android:shape="ring" 圆环
android:thickness="3dp" 厚度为3dp
android:useLevel="false" > 去掉默认动画
<gradient 颜色为渐变
android:centerColor="#3f00" 起始颜色
android:endColor="#f00" 终点颜色
android:startColor="#fff" /> 中间颜色
</shape>
</rotate> --> android:visibility="invisible" />
</FrameLayout> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical" > <TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="#f00"
android:textSize="16sp" /> <TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="最后刷新时间:2015-03-10 17:07:07"
android:textColor="@android:color/darker_gray"
android:textSize="14sp" />
</LinearLayout> </LinearLayout>
刷新尾:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" > <ProgressBar
android:id="@+id/pb_pull_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:indeterminateDrawable="@drawable/custom_progress" />
<!--
custom_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
<shape
android:innerRadius="12dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false" >
<gradient
android:centerColor="#3f00"
android:endColor="#f00"
android:startColor="#fff" />
</shape>
</rotate> -->
<TextView
android:id="@+id/tv_pull_list_header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载中..."
android:textColor="#ff0000"
android:textSize="18sp" /> </LinearLayout>
新闻详情页:
package com.itheima.zhbj52; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.TextSize;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import cn.sharesdk.framework.ShareSDK;
import cn.sharesdk.onekeyshare.OnekeyShare;
import cn.sharesdk.onekeyshare.OnekeyShareTheme; /**
* 新闻详情页
*/
public class NewsDetailActivity extends Activity implements OnClickListener { private WebView mWebView;
private ImageButton btnBack;
private ImageButton btnSize;
private ImageButton btnShare; private ProgressBar pbProgress; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_news_detail); mWebView = (WebView) findViewById(R.id.wv_web);
btnBack = (ImageButton) findViewById(R.id.btn_back);
btnSize = (ImageButton) findViewById(R.id.btn_size);
btnShare = (ImageButton) findViewById(R.id.btn_share); btnBack.setOnClickListener(this);
btnSize.setOnClickListener(this);
btnShare.setOnClickListener(this); pbProgress = (ProgressBar) findViewById(R.id.pb_progress); String url = getIntent().getStringExtra("url");
//WebView的属性
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);// 表示支持js
settings.setBuiltInZoomControls(true);// 显示放大缩小按钮
settings.setUseWideViewPort(true);// 支持双击缩放 mWebView.setWebViewClient(new WebViewClient() {//回调
/**
* 网页开始加载时回调
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
System.out.println("网页开始加载");
pbProgress.setVisibility(View.VISIBLE);//进度条显示
}
/**
* 网页加载结束时回调
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
System.out.println("网页开始结束");
pbProgress.setVisibility(View.GONE);//进度条隐藏
}
/**
* 所有点击的跳转的链接都会在此方法中回调
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// tel:110
System.out.println("跳转url:" + url);
view.loadUrl(url);//如果不写这,那么url跳转的时候就是用的网页,这里强制不使用网页使用WebView加载url。
return true;
// return super.shouldOverrideUrlLoading(view, url);
}
});
// mWebView.goBack() mWebView.setWebChromeClient(new WebChromeClient() {
/**
* 网页加载进度发生变化(加载的时候一直调用)
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
System.out.println("加载进度:" + newProgress);
super.onProgressChanged(view, newProgress);
}
/**
* 获取网页标题
*/
@Override
public void onReceivedTitle(WebView view, String title) {
System.out.println("网页标题:" + title);
super.onReceivedTitle(view, title);
}
}); mWebView.loadUrl(url);// 加载网页,前面的setWebViewClient和setWebChromeClient不要也可以。
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back://返回,就是销毁当前页面
finish();
break;
case R.id.btn_size:
showChooseDialog();//设置字体
break;
case R.id.btn_share:
showShare();//ShareSDK第三方分享平台,集成了其他平台的接口。
break;
default:
break;
}
} private int mCurrentChooseItem;// 记录当前选中的item, 点击确定前
private int mCurrentItem = 2;// 记录当前选中的item, 点击确定后 /**
* 显示选择对话框
*/
private void showChooseDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String[] items = new String[] { "超大号字体", "大号字体", "正常字体", "小号字体",
"超小号字体" };
builder.setTitle("字体设置");
builder.setSingleChoiceItems(items, mCurrentItem,///mCurrentItem是默认选中的当前字体
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {//这个which是当前选中项,
System.out.println("选中:" + which);
mCurrentChooseItem = which;//现在新选择的字体
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {//这个which永远是0,
WebSettings settings = mWebView.getSettings();
switch (mCurrentChooseItem) {
case 0:
settings.setTextSize(TextSize.LARGEST);
break;
case 1:
settings.setTextSize(TextSize.LARGER);
break;
case 2:
settings.setTextSize(TextSize.NORMAL);
break;
case 3:
settings.setTextSize(TextSize.SMALLER);
break;
case 4:
settings.setTextSize(TextSize.SMALLEST);
break; default:
break;
}
mCurrentItem = mCurrentChooseItem;//先前选择的字体
}
});
builder.setNegativeButton("取消", null);//不需要dismiss,系统默认就会dismiss,
builder.show();
} /**
* 分享, 注意在sdcard根目录放test.jpg
*/
private void showShare() {
ShareSDK.initSDK(this);
OnekeyShare oks = new OnekeyShare(); oks.setTheme(OnekeyShareTheme.SKYBLUE);//设置天蓝色的主题 // 关闭sso授权
oks.disableSSOWhenAuthorize(); // 分享时Notification的图标和文字
oks.setNotification(R.drawable.ic_launcher,
getString(R.string.app_name));
// title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用
oks.setTitle(getString(R.string.share));
// 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"); // 启动分享GUI
oks.show(this);
}
}
activity_news_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_red_bg" > <ImageButton
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:background="@null"
android:src="@drawable/back" /> 后退按钮 <ImageButton
android:id="@+id/btn_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:background="@null"
android:src="@drawable/icon_share" /> 分享按钮 <ImageButton
android:id="@+id/btn_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:layout_toLeftOf="@id/btn_share" 在分享按钮左边
android:background="@null"
android:src="@drawable/icon_textsize" /> 设置文字大小的按钮
</RelativeLayout> <!-- 帧布局里面的控件可以叠加 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<!-- WebView用来加载来自网页的数据(跟网页一样的布局) -->
<WebView
android:id="@+id/wv_web"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- 网页加载进度的滚动条 -->
<ProgressBar
android:id="@+id/pb_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/custom_progress" />
<?xml version="1.0" encoding="utf-8"?>
<!-- <rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
<shape
android:innerRadius="12dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false" >
<gradient
android:centerColor="#3f00"
android:endColor="#f00"
android:startColor="#fff" />
</shape>
</rotate> -->
</FrameLayout>
</LinearLayout>
android124 zhihuibeijing 新闻中心-新闻 -北京页签 下拉刷新的更多相关文章
- 指令汇B新闻客户端开发(三) 下拉刷新
现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能.我这个应用是通过拉ListView来实现刷新的,先看一张刷新的原理图 从图中可知,手指移 ...
- android新闻项目、饮食助手、下拉刷新、自定义View进度条、ReactNative阅读器等源码
Android精选源码 Android仿照36Kr官方新闻项目课程源码 一个优雅美观的下拉刷新布局,众多样式可选 安卓版本的VegaScroll滚动布局 android物流详情的弹框 健身饮食记录助手 ...
- android123 zhihuibeijing 新闻中心-新闻 页签 ViewPagerIndicator实现
## ViewPagerIndicator ## 使用导入ViewPagerIndicator库的方式相当于可以改源码,打包编译Eclips可以自动完成. ViewPager指针项目,在使用ViewP ...
- 关于mui中一个页面有有多个页签进行切换的下拉刷新加搜索问题
此图是最近做的项目中的一页,用的是mui结合vue,用了mui后,觉得是真心难用啊,先不说其他的,就光这个下拉刷新就让人奔溃了,问题层出不穷,不过最后经过努力还是摆平了哈. 1.每次切换到新的标签,都 ...
- iscroll的下拉刷新,上拉翻页。
首先对iscroll的scrollTo方法进行稍微修改如下图: 对iscroll滑动到屏幕边缘不能弹回的bug进行修复,如下代码: function scrollbug() { var self = ...
- 安卓ListView行详细内容展示页编写和下拉刷新实现
ListView行详细内容展示页: 使用轻量级的Fragment实现Listview行内容简单的详细信息展示: 值得注意的是: 1. 主布局(打开它的Activity)必须是FrameLayout布局 ...
- vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件
vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件/库 一提到移动端的下拉刷新上拉翻页,你可能就会想到iScroll插件,没错iScroll是一个高性能,资源 ...
- Android 聊天表情输入、表情翻页带效果、下拉刷新聊天记录
经过一个星期的折腾,最终做完了这个Android 聊天表情输入.表情翻页带效果.下拉刷新聊天记录.这仅仅是一个单独聊天表情的输入,以及聊天的效果实现.由于我没有写server,所以没有两方聊天的效果. ...
- 小程序组件-swipe多页切换,并支持下拉刷新,上拉加载,menu动态联动切换
前言 最近一个小程序项目中遇到一个需求,就是实现类似资讯类app的多页面切换的那种效果, 如下图: 最终效果: 1.功能分析 首先实现这个功能分为三步: 实现顶部menu菜单 实现多页面滑动切换 支持 ...
随机推荐
- (转载)Web存储和SessionStorage locaStorage
<转> sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据.有了本地数据,就可以避免数据在 ...
- Java [Leetcode 42]Trapping Rain Water
题目描述: Given n non-negative integers representing an elevation map where the width of each bar is 1, ...
- Java [leetcode 29]Divide Two Integers
题目描述: Divide two integers without using multiplication, division and mod operator. If it is overflow ...
- 15个实用的Linux find命令示例(一)
除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使你的命令行之旅更加简易. 本文将介绍15种无论是于新手还是老鸟都非常有用的Linux find命令. 首先,在你 ...
- CF GYM 100703K Word order
题意:给一个字符串,其中只有F.A.N三种字母,问最少交换多少次能使所有的A在所有F之前. 解法:贪心.先预处理每位的左边有多少F右边有多少A,对于每位A必须至少向左交换的次数为它左面的F个数,而对于 ...
- SQL中的CASE WHEN用法
其语法如下: 1)case vlaue when [compare-value]then reslut [when[compare-value]] then result ...] [else res ...
- A Fast Priority Queue Implementation of the Dijkstra Shortest Path Algorithm
http://www.codeproject.com/Articles/24816/A-Fast-Priority-Queue-Implementation-of-the-Dijkst http:// ...
- HDU5046 Airport dancing links 重复覆盖+二分
这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...
- Codeforces 633 C Spy Syndrome 2 字典树
题意:还是比较好理解 分析:把每个单词反转,建字典树,然后暴力匹配加密串 注:然后我就是特别不理解,上面那种能过,而且时间很短,但是我想反之亦然啊 我一开始写的是,把加密串进行反转,然后单词正着建字典 ...
- POJ3616 Milking Time 简单DP
注意0,1,.....,N是时间点,i~i+1是时间段 然后就是思路:dp[i]代表到时间点 i 获得的最大价值, 1:dp[i]=max(dp[i],dp[s-r]+e),表示有以s为开头,i为结尾 ...