Android
来源:互联网 发布:livin on a prayer知乎 编辑:程序博客网 时间:2024/05/21 13:59
最近项目已经接近尾声了,由于一些原因,我可能又要找新的工作了,啊啊啊,有点忧伤。
之前有在新浪写过一写博客,现在准备在CSDN上写博客了,CSDN博客-最大IT写作分享平台,很多资料都可以在这找到,所有我也搬家了。
自己也写了好几个项目了,但是博客还没有多少,其实有很多东西都需要记记得,温故而知新嘛!趁不忙,就记录记录。
好了 ,上面的可以忽略,下面正式开始了!
下拉刷新,上拉加载更多
地址:https://github.com/captainbupt/android-Ultra-Pull-To-Refresh-With-Load-More
优点:
这个框架的扩展性还是很强的,头部和底部都可以自定义,
它其中可以嵌套任何控件,ListView、GridView、ScrollView、RecyclerView,甚至TextView。
更多样式参照GitHub中的源码
一.jar包的引用
开发工具是AS
在gradle添加到项目中,我这里是1.0.6,最新版可以到githup上看
compile 'in.srain.cube:ptr-load-more:1.0.6'
二、使用方法
首先在你需要刷新和加载的地方,最外层加入
in.srain.cube.views.ptr.PtrClassicFrameLayout
以我的为例,我这是给gridview加刷新和加载更多
在xml中
<!-- ptr:ptr_duration_to_close_either:头部和底部回弹时间 ptr:ptr_keep_header_when_refresh:刷新过程中是否保留头部 ptr:ptr_pull_to_fresh:下拉刷新/释放刷新,默认是释放刷新 ptr:ptr_ratio_of_header_height_to_refresh:触发刷新时移动的位置比例,指的是与头部的比例 ptr:ptr_resistance:阻尼系数,越大下拉越吃力 --><in.srain.cube.views.ptr.PtrClassicFrameLayout android:id="@+id/rotate_header_grid_view_frame" android:layout_width="match_parent" android:layout_height="match_parent" app:ptr_duration_to_close_either="1000" app:ptr_keep_header_when_refresh="true" app:ptr_pull_to_fresh="false" app:ptr_ratio_of_header_height_to_refresh="1.2" app:ptr_resistance="1.7"> <GridView android:id="@+id/myPoints_gridview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="@dimen/margin_ten" android:layout_marginLeft="@dimen/margin_ten" android:layout_marginRight="@dimen/margin_ten" android:layout_marginTop="@dimen/margin_ten" android:fadingEdge="none" android:horizontalSpacing="@dimen/margin_ten" android:listSelector="@android:color/transparent" android:numColumns="2" android:overScrollMode="never" android:scrollbars="none" android:verticalSpacing="@dimen/margin_ten"></GridView></in.srain.cube.views.ptr.PtrClassicFrameLayout>
在Activity中
使用默认样式
//初始化
@ViewInject(R.id.rotate_header_grid_view_frame)private PtrClassicFrameLayout mPtrFrame;
//在oncreate中
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_points); initReFresh();}
/** * 设置下拉刷新上拉加载 */private void initReFresh() { //设置下拉刷新上拉加载 mPtrFrame.disableWhenHorizontalMove(true);//解决横向滑动冲突 mPtrFrame.setPtrHandler(new PtrDefaultHandler2() { @Override public void onRefreshBegin(PtrFrameLayout frame) { mPtrFrame.postDelayed(new Runnable() { @Override public void run() { //刷新数据 } }, 1000); } @Override public void onLoadMoreBegin(PtrFrameLayout frame) { mPtrFrame.postDelayed(new Runnable() { @Override public void run() { //加载更多 } }, 1000); } @Override public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) { return super.checkCanDoLoadMore(frame, gridView, footer); } @Override public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { return super.checkCanDoRefresh(frame, gridView, header); } } );}//结束刷新和加载更多的动画,在你成功请求到数据后写入
mPtrFrame.refreshComplete();
默认样式就是这样了
自定义头的部和底部
自定时都继承PtrUIHandler
自定义的头部文件
MyHeadView
package com.example.ruidun.ShanXunApplication.view;import android.content.Context;import android.os.Handler;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.ProgressBar;import android.widget.TextView;import com.example.ruidun.ShanXunApplication.R;import in.srain.cube.views.ptr.PtrFrameLayout;import in.srain.cube.views.ptr.PtrUIHandler;import in.srain.cube.views.ptr.indicator.PtrIndicator;/** * * 项目名称:¥{PROJECT_NAME} * 创建人:潇潇 * */public class MyHeadView extends FrameLayout implements PtrUIHandler { private TextView tvLoading; private View view; //箭头 private ImageView mArrowImageView; //开始加载的动画 private ProgressBar mProgressBar; //动画 private Animation mRotateUpAnim; //显示当前进度的textview private TextView mHintTextView; private Animation mRotateDownAnim; private final int ROTATE_ANIM_DURATION = 180; public MyHeadView(Context context) { this(context, null); } public MyHeadView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyHeadView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } //实例化控件 private void init() { view = LayoutInflater.from(getContext()).inflate(R.layout.xlistview_header, this, false); addView(view); tvLoading = (TextView) view.findViewById(R.id.xlistview_header_hint_textview); mArrowImageView = (ImageView) view.findViewById(R.id.xlistview_header_arrow); mProgressBar = (ProgressBar) view.findViewById(R.id.xlistview_header_progressbar); mHintTextView = (TextView) view.findViewById(R.id.xlistview_header_hint_textview);// 初始情况,设置下拉刷新view高度为0 mRotateUpAnim = new RotateAnimation(0.0f, -180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION); mRotateUpAnim.setFillAfter(true); mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION); mRotateDownAnim.setFillAfter(true); } //重写方法 @Override public void onUIReset(PtrFrameLayout frame) { //重置 } @Override public void onUIRefreshPrepare(PtrFrameLayout frame) { //准备刷新 //重置时,将动画置为初始状态 mArrowImageView.clearAnimation(); mArrowImageView.startAnimation(mRotateUpAnim); mHintTextView.setText(R.string.xlistview_header_hint_ready); } @Override public void onUIRefreshBegin(PtrFrameLayout frame) { //开始刷新 显示刷新进度跟文本 //开始刷新,启动动画 mArrowImageView.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.VISIBLE); tvLoading.setText("正在加载"); } @Override public void onUIRefreshComplete(PtrFrameLayout frame, boolean isHeader) { //刷新完成 设置文本 设置进度隐藏 tvLoading.setText("加载完毕"); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mArrowImageView.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.INVISIBLE); } }, 500); } @Override public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) { final int mOffsetToRefresh = frame.getOffsetToRefresh(); final int currentPos = ptrIndicator.getCurrentPosY(); final int lastPos = ptrIndicator.getLastPosY(); if (currentPos < mOffsetToRefresh) { //未到达刷新线 if (status == PtrFrameLayout.PTR_STATUS_PREPARE) { mArrowImageView.startAnimation(mRotateDownAnim); tvLoading.setText("下拉刷新"); } } else if (currentPos > mOffsetToRefresh) { //到达或超过刷新线 if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) { mArrowImageView.clearAnimation(); tvLoading.setText("释放刷新"); } } } //设置背景色 public void setHeadColor(int color) { view.setBackgroundColor(color); }}
自定义底部布局跟自定义头布局都是一样
MyFooterView
package com.example.ruidun.ShanXunApplication.view;import android.content.Context;import android.content.SharedPreferences;import android.content.res.TypedArray;import android.text.TextUtils;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.animation.LinearInterpolator;import android.view.animation.RotateAnimation;import android.widget.FrameLayout;import android.widget.TextView;import com.example.ruidun.ShanXunApplication.R;import java.text.SimpleDateFormat;import java.util.Date;import in.srain.cube.views.ptr.PtrFrameLayout;import in.srain.cube.views.ptr.PtrUIHandler;import in.srain.cube.views.ptr.indicator.PtrIndicator;/** * * 项目名称:¥{PROJECT_NAME} * 创建人:潇潇 * */public class MyFooterView extends FrameLayout implements PtrUIHandler { private final static String KEY_SharedPreferences = "cube_ptr_classic_last_update"; private static SimpleDateFormat sDataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private int mRotateAniTime = 150; protected RotateAnimation mFlipAnimation; protected RotateAnimation mReverseFlipAnimation; //当前加载进度描述 protected TextView mTitleTextView; //加载动画 private View mProgressBar; private long mLastUpdateTime = -1; private String mLastUpdateTimeKey; private boolean mShouldShowLastUpdate; private MyFooterView.LastUpdateTimeUpdater mLastUpdateTimeUpdater = new MyFooterView.LastUpdateTimeUpdater(); public MyFooterView(Context context) { super(context); initViews(null); } public MyFooterView(Context context, AttributeSet attrs) { super(context, attrs); initViews(attrs); } public MyFooterView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initViews(attrs); } //初始化布局 protected void initViews(AttributeSet attrs) { TypedArray arr = getContext().obtainStyledAttributes(attrs, in.srain.cube.views.ptr.R.styleable.PtrClassicHeader, 0, 0); if (arr != null) { mRotateAniTime = arr.getInt(in.srain.cube.views.ptr.R.styleable.PtrClassicHeader_ptr_rotate_ani_time, mRotateAniTime); } buildAnimation(); View header = LayoutInflater.from(getContext()).inflate(R.layout.xlistview_footer, this); mTitleTextView = (TextView) header.findViewById(R.id.xlistview_footer_hint_textview); mProgressBar = header.findViewById(R.id.xlistview_footer_progressbar); resetView(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mLastUpdateTimeUpdater != null) { mLastUpdateTimeUpdater.stop(); } } public void setRotateAniTime(int time) { if (time == mRotateAniTime || time == 0) { return; } mRotateAniTime = time; buildAnimation(); } /** * Specify the last update time by this key string * * @param key */ public void setLastUpdateTimeKey(String key) { if (TextUtils.isEmpty(key)) { return; } mLastUpdateTimeKey = key; } /** * Using an object to specify the last update time. * * @param object */ public void setLastUpdateTimeRelateObject(Object object) { setLastUpdateTimeKey(object.getClass().getName() + "footer"); } //加载时的动画效果 protected void buildAnimation() { mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mFlipAnimation.setInterpolator(new LinearInterpolator()); mFlipAnimation.setDuration(mRotateAniTime); mFlipAnimation.setFillAfter(true); mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); mReverseFlipAnimation.setDuration(mRotateAniTime); mReverseFlipAnimation.setFillAfter(true); } private void resetView() { hideRotateView(); mProgressBar.setVisibility(INVISIBLE); } private void hideRotateView() {// mRotateView.clearAnimation();// mRotateView.setVisibility(INVISIBLE); } @Override public void onUIReset(PtrFrameLayout frame) { //重置 resetView(); mShouldShowLastUpdate = true; tryUpdateLastUpdateTime(); } @Override public void onUIRefreshPrepare(PtrFrameLayout frame) { //准备加载更多 //重置时,将动画置为初始状态 mShouldShowLastUpdate = true; tryUpdateLastUpdateTime(); mLastUpdateTimeUpdater.start(); mProgressBar.setVisibility(INVISIBLE);// mRotateView.setVisibility(VISIBLE); mTitleTextView.setVisibility(VISIBLE); if (frame.isPullToRefresh()) { //释放加载 mTitleTextView.setText("松开载入更多"); } else { //上拉 mTitleTextView.setText("查看更多"); } } @Override public void onUIRefreshBegin(PtrFrameLayout frame) { //开始加载 mShouldShowLastUpdate = false; hideRotateView(); mProgressBar.setVisibility(VISIBLE); //正在加载中 mTitleTextView.setVisibility(GONE); mTitleTextView.setText(in.srain.cube.views.ptr.R.string.cube_ptr_loading); tryUpdateLastUpdateTime(); mLastUpdateTimeUpdater.stop(); } @Override public void onUIRefreshComplete(PtrFrameLayout frame, boolean isHeader) { //加载完成 if (isHeader) { return; } hideRotateView(); mProgressBar.setVisibility(INVISIBLE); //加载完成 mTitleTextView.setVisibility(VISIBLE); mTitleTextView.setText(getResources().getString(in.srain.cube.views.ptr.R.string.cube_ptr_load_complete)); // update last update time SharedPreferences sharedPreferences = getContext().getSharedPreferences(KEY_SharedPreferences, 0); if (!TextUtils.isEmpty(mLastUpdateTimeKey)) { mLastUpdateTime = new Date().getTime(); sharedPreferences.edit().putLong(mLastUpdateTimeKey, mLastUpdateTime).commit(); } } private void tryUpdateLastUpdateTime() { if (TextUtils.isEmpty(mLastUpdateTimeKey) || !mShouldShowLastUpdate) { } else { String time = getLastUpdateTime(); if (TextUtils.isEmpty(time)) { } else { } } } private String getLastUpdateTime() { if (mLastUpdateTime == -1 && !TextUtils.isEmpty(mLastUpdateTimeKey)) { mLastUpdateTime = getContext().getSharedPreferences(KEY_SharedPreferences, 0).getLong(mLastUpdateTimeKey, -1); } if (mLastUpdateTime == -1) { return null; } long diffTime = new Date().getTime() - mLastUpdateTime; int seconds = (int) (diffTime / 1000); if (diffTime < 0) { return null; } if (seconds <= 0) { return null; } StringBuilder sb = new StringBuilder(); sb.append(getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_last_update)); if (seconds < 60) { sb.append(seconds + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_seconds_ago)); } else { int minutes = (seconds / 60); if (minutes > 60) { int hours = minutes / 60; if (hours > 24) { Date date = new Date(mLastUpdateTime); sb.append(sDataFormat.format(date)); } else { sb.append(hours + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_hours_ago)); } } else { sb.append(minutes + getContext().getString(in.srain.cube.views.ptr.R.string.cube_ptr_minutes_ago)); } } return sb.toString(); } @Override public void onUIPositionChange(PtrFrameLayout frame, boolean isUnderTouch, byte status, PtrIndicator ptrIndicator) { final int mOffsetToRefresh = frame.getOffsetToRefresh(); final int currentPos = ptrIndicator.getCurrentPosY(); final int lastPos = ptrIndicator.getLastPosY(); if (currentPos < mOffsetToRefresh && lastPos >= mOffsetToRefresh) { if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) { crossRotateLineFromBottomUnderTouch(frame);// if (mRotateView != null) {// mRotateView.clearAnimation();// mRotateView.startAnimation(mReverseFlipAnimation);// } } } else if (currentPos > mOffsetToRefresh && lastPos <= mOffsetToRefresh) { if (isUnderTouch && status == PtrFrameLayout.PTR_STATUS_PREPARE) { crossRotateLineFromTopUnderTouch(frame);// if (mRotateView != null) {// mRotateView.clearAnimation();// mRotateView.startAnimation(mFlipAnimation);// } } } } private void crossRotateLineFromTopUnderTouch(PtrFrameLayout frame) { if (!frame.isPullToRefresh()) { mTitleTextView.setVisibility(VISIBLE); mTitleTextView.setText("松开载入更多"); } } private void crossRotateLineFromBottomUnderTouch(PtrFrameLayout frame) { mTitleTextView.setVisibility(VISIBLE); if (frame.isPullToRefresh()) { mTitleTextView.setText("松开载入更多"); } else { mTitleTextView.setText("查看更多"); } } private class LastUpdateTimeUpdater implements Runnable { private boolean mRunning = false; private void start() { if (TextUtils.isEmpty(mLastUpdateTimeKey)) { return; } mRunning = true; run(); } private void stop() { mRunning = false; removeCallbacks(this); } @Override public void run() { tryUpdateLastUpdateTime(); if (mRunning) { postDelayed(this, 1000); } } }}
在Activity中使用吧头布局和底部加上就ok了
/** * 设置下拉刷新上拉加载 */private void initReFresh() { MyFooterView fView = new MyFooterView(MyPointsActivity.this);//自定义底部加载更多 mPtrFrame.setFooterView(fView); mPtrFrame.addPtrUIHandler(fView); MyHeadView hView = new MyHeadView(MyPointsActivity.this); //自定义头部 刷新 mPtrFrame.setKeepHeaderWhenRefresh(true);//刷新时保留头部 mPtrFrame.setHeaderView(hView); mPtrFrame.addPtrUIHandler(hView); //设置下拉刷新上拉加载 mPtrFrame.disableWhenHorizontalMove(true);//解决横向滑动冲突 mPtrFrame.setPtrHandler(new PtrDefaultHandler2() { @Override public void onRefreshBegin(PtrFrameLayout frame) { mPtrFrame.postDelayed(new Runnable() { @Override public void run() { //刷新 } }, 1000); } @Override public void onLoadMoreBegin(PtrFrameLayout frame) { mPtrFrame.postDelayed(new Runnable() { @Override public void run() { //加载更多 } }, 1000); } @Override public boolean checkCanDoLoadMore(PtrFrameLayout frame, View content, View footer) { return super.checkCanDoLoadMore(frame, gridView, footer); } @Override public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { return super.checkCanDoRefresh(frame, gridView, header); } } );}
阅读全文
1 0
- Android
- android
- Android
- android
- android
- Android
- Android
- android
- android
- android
- Android
- Android
- android!!!
- android
- android
- android
- android
- android:
- numpy-数组对象ndarray
- 2018校招三七互娱软件测试岗笔试题
- Divide and Conquer -- Leetcode problem240. Search a 2D Matrix II
- IEnumerable和IEnumerator
- Chart.js使用
- Android
- lstm+crf实现命名实体识别
- 闪屏页(二)
- C/C++ 大数加法 动态分配内存
- 浅谈css3的轮播图
- 题目96-n-1位数
- MYSQL数据库四种索引类型的简单使用
- 浏览器的渲染机制
- Mac配置dubbo-admin并启动