package com.loaderman.androiddemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView; public class XListView extends ListView implements OnScrollListener { private float mLastY = -1; // save event y
private Scroller mScroller; // used for scroll back
private OnScrollListener mScrollListener; // user's scroll listener // the interface to trigger refresh and load more.
private IXListViewListener mListViewListener; // -- header view
private XListViewHeader mHeaderView;
// header view content, use it to calculate the Header's height. And hide it
// when disable pull refresh.
private RelativeLayout mHeaderViewContent;
private TextView mHeaderTimeView;
private int mHeaderViewHeight; // header view's height
private boolean mEnablePullRefresh = true;
private boolean mPullRefreshing = false; // is refreashing. // -- footer view
private XListViewFooter mFooterView;
private boolean mEnablePullLoad;
private boolean mPullLoading;
private boolean mIsFooterReady = false; // total list items, used to detect is at the bottom of listview.
private int mTotalItemCount; // for mScroller, scroll back from header or footer.
private int mScrollBack;
private final static int SCROLLBACK_HEADER = 0;
private final static int SCROLLBACK_FOOTER = 1; private final static int SCROLL_DURATION = 400; // scroll back duration
private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px
// at bottom, trigger
// load more.
private final static float OFFSET_RADIO = 1.8f; // support iOS like pull
// feature. /**
* @param context
*/
public XListView(Context context) {
super(context);
initWithContext(context);
} public XListView(Context context, AttributeSet attrs) {
super(context, attrs);
initWithContext(context);
} public XListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWithContext(context);
} private void initWithContext(Context context) {
mScroller = new Scroller(context, new DecelerateInterpolator());
// XListView need the scroll event, and it will dispatch the event to
// user's listener (as a proxy).
super.setOnScrollListener(this); // init header view
mHeaderView = new XListViewHeader(context);
mHeaderViewContent = (RelativeLayout) mHeaderView .findViewById(R.id.xlistview_header_content);
mHeaderTimeView = (TextView) mHeaderView .findViewById(R.id.xlistview_header_time);
addHeaderView(mHeaderView); // init footer view
mFooterView = new XListViewFooter(context); // init header height
mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
mHeaderViewHeight = mHeaderViewContent.getHeight();
getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
} @Override
public void setAdapter(ListAdapter adapter) {
// make sure XListViewFooter is the last footer view, and only add once.
if (mIsFooterReady == false) {
mIsFooterReady = true;
addFooterView(mFooterView);
}
super.setAdapter(adapter);
} /**
* enable or disable pull down refresh feature.
*
* @param enable
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
if (!mEnablePullRefresh) { // disable, hide the content
mHeaderViewContent.setVisibility(View.INVISIBLE);
} else {
mHeaderViewContent.setVisibility(View.VISIBLE);
}
} /**
* enable or disable pull up load more feature.
*
* @param enable
*/
public void setPullLoadEnable(boolean enable) {
mEnablePullLoad = enable;
if (!mEnablePullLoad) {
mFooterView.hide();
mFooterView.setOnClickListener(null);
} else {
mPullLoading = false;
mFooterView.show();
mFooterView.setState(XListViewFooter.STATE_NORMAL);
// both "pull up" and "click" will invoke load more.
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startLoadMore();
}
});
}
} /**
* stop refresh, reset header view.
*/
public void stopRefresh() {
if (mPullRefreshing == true) {
mPullRefreshing = false;
resetHeaderHeight();
}
} /**
* stop load more, reset footer view.
*/
public void stopLoadMore() {
if (mPullLoading == true) {
mPullLoading = false;
mFooterView.setState(XListViewFooter.STATE_NORMAL);
}
} /**
* set last refresh time
*
* @param time
*/
public void setRefreshTime(String time) {
mHeaderTimeView.setText(time);
} private void invokeOnScrolling() {
if (mScrollListener instanceof OnXScrollListener) {
OnXScrollListener l = (OnXScrollListener) mScrollListener;
l.onXScrolling(this);
}
} private void updateHeaderHeight(float delta) {
mHeaderView.setVisiableHeight((int) delta
+ mHeaderView.getVisiableHeight());
if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头
if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
mHeaderView.setState(XListViewHeader.STATE_READY);
} else {
mHeaderView.setState(XListViewHeader.STATE_NORMAL);
}
}
setSelection(0); // scroll to top each time
} /**
* reset header view's height.
*/
private void resetHeaderHeight() {
int height = mHeaderView.getVisiableHeight();
if (height == 0) // not visible.
return;
// refreshing and header isn't shown fully. do nothing.
if (mPullRefreshing && height <= mHeaderViewHeight) {
return;
}
int finalHeight = 0; // default: scroll back to dismiss header.
// is refreshing, just scroll back to show all the header.
if (mPullRefreshing && height > mHeaderViewHeight) {
finalHeight = mHeaderViewHeight;
}
mScrollBack = SCROLLBACK_HEADER;
mScroller.startScroll(0, height, 0, finalHeight - height,
SCROLL_DURATION);
// trigger computeScroll
invalidate();
} private void updateFooterHeight(float delta) {
int height = mFooterView.getBottomMargin() + (int) delta;
if (mEnablePullLoad && !mPullLoading) {
if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke loadmore.
mFooterView.setState(XListViewFooter.STATE_READY);
} else {
mFooterView.setState(XListViewFooter.STATE_NORMAL);
}
}
mFooterView.setBottomMargin(height); // setSelection(mTotalItemCount - 1); // scroll to bottom
} private void resetFooterHeight() {
int bottomMargin = mFooterView.getBottomMargin();
if (bottomMargin > 0) {
mScrollBack = SCROLLBACK_FOOTER;
mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,
SCROLL_DURATION);
invalidate();
}
} private void startLoadMore() {
mPullLoading = true;
mFooterView.setState(XListViewFooter.STATE_LOADING);
if (mListViewListener != null) {
mListViewListener.onLoadMore();
}
} @Override
public boolean onTouchEvent(MotionEvent ev) {
if (mLastY == -1) {
mLastY = ev.getRawY();
} switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
final float deltaY = ev.getRawY() - mLastY;
mLastY = ev.getRawY();
if (getFirstVisiblePosition() == 0
&& (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
// the first item is showing, header has shown or pull down.
updateHeaderHeight(deltaY / OFFSET_RADIO);
invokeOnScrolling();
} else if (getLastVisiblePosition() == mTotalItemCount - 1
&& (mFooterView.getBottomMargin() > 0 || deltaY < 0) && getCount()>10) {
// last item, already pulled up or want to pull up.
updateFooterHeight(-deltaY / OFFSET_RADIO);
}
break;
default:
mLastY = -1; // reset
if (getFirstVisiblePosition() == 0) {
// invoke refresh
if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
mPullRefreshing = true;
mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
if (mListViewListener != null) {
mListViewListener.onRefresh();
}
}
resetHeaderHeight();
} else if (getLastVisiblePosition() == mTotalItemCount - 1) {
// invoke load more.
if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {
startLoadMore();
}
resetFooterHeight();
}
break;
}
return super.onTouchEvent(ev);
} @Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLLBACK_HEADER) {
mHeaderView.setVisiableHeight(mScroller.getCurrY());
} else {
mFooterView.setBottomMargin(mScroller.getCurrY());
}
postInvalidate();
invokeOnScrolling();
}
super.computeScroll();
} @Override
public void setOnScrollListener(OnScrollListener l) {
mScrollListener = l;
} @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
} @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// send to user's listener
mTotalItemCount = totalItemCount;
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
totalItemCount);
}
} public void setXListViewListener(IXListViewListener l) {
mListViewListener = l;
} /**
* you can listen ListView.OnScrollListener or this one. it will invoke
* onXScrolling when header/footer scroll back.
*/
public interface OnXScrollListener extends OnScrollListener {
public void onXScrolling(View view);
} /**
* implements this interface to get refresh/load more event.
*/
public interface IXListViewListener {
public void onRefresh(); public void onLoadMore();
} public void setFooterBackgroundRes(int resId) {
if (mFooterView != null) {
mFooterView.setBackgroundResource(resId);
}
}
public void setFooterBackgroundColor(int resId) {
if (mFooterView != null) {
mFooterView.setBackgroundColor(resId);
mFooterView.invalidate();
}
} /**
* 是否处于加载更多的状态
* @return
*/
public boolean isLoading(){
return mPullLoading;
}
// public void showRefresh() {
// mPullRefreshing = true;
// mHeaderView.setVisiableHeight(mHeaderViewHeight);
// mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
// mListViewListener.onRefresh();
// }
}
package com.loaderman.androiddemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; public class XListViewFooter extends LinearLayout {
public final static int STATE_NORMAL = 0;
public final static int STATE_READY = 1;
public final static int STATE_LOADING = 2; private Context mContext; private View mContentView;
private TextView mHintView;
private ImageView mLoadIcon;
private Animation animation; public XListViewFooter(Context context) {
super(context);
initView(context);
} public XListViewFooter(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
} public void setState(int state) {
switch (state) {
case STATE_READY:
mLoadIcon.clearAnimation();
mLoadIcon.setImageResource(R.drawable.icon_loading_not_selected);
mHintView.setText(R.string.xlistview_footer_hint_ready);
break;
case STATE_LOADING:
mHintView.setText(R.string.xlistview_header_hint_loading);
mLoadIcon.setImageResource(R.drawable.icon_loading_selected);
mLoadIcon.startAnimation(animation);
break;
default:
mLoadIcon.clearAnimation();
mHintView.setText(R.string.xlistview_footer_hint_normal);
mLoadIcon.setImageResource(R.drawable.icon_loading_not_selected);
break;
}
} public void setBottomMargin(int height) {
if (height < 0) return ;
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.bottomMargin = height;
mContentView.setLayoutParams(lp);
} public int getBottomMargin() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
return lp.bottomMargin;
} /**
* normal status
*/
public void normal() {
mHintView.setVisibility(View.VISIBLE);
} /**
* loading status
*/ public void loading() {
mHintView.setVisibility(View.GONE);
mHintView.setText(R.string.xlistview_header_hint_loading);
mLoadIcon.setImageResource(R.drawable.icon_loading_selected);
} /**
* hide footer when disable pull load more
*/ public void hide() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.height = 0;
mContentView.setLayoutParams(lp);
} /**
* show footer
*/ public void show() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.height = LayoutParams.WRAP_CONTENT;
mContentView.setLayoutParams(lp);
} private void initView(Context context) {
mContext = context;
LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);
addView(moreView);
moreView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); mContentView = moreView.findViewById(R.id.xlistview_footer_content);
mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);
mLoadIcon = (ImageView) moreView.findViewById(R.id.iv_load);
animation = AnimationUtils.loadAnimation(mContext, R.anim.loadmore);
LinearInterpolator lin = new LinearInterpolator();
animation.setInterpolator(lin);
} }
package com.loaderman.androiddemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; public class XListViewHeader extends LinearLayout {
private LinearLayout mContainer;
private ImageView mArrowImageView;
private TextView mHintTextView;
private int mState = STATE_NORMAL; private Animation mRotateUpAnim;
private Animation mRotateDownAnim; private final int ROTATE_ANIM_DURATION = 180; public final static int STATE_NORMAL = 0;
public final static int STATE_READY = 1;
public final static int STATE_REFRESHING = 2;
private Animation mPBAnimation; public XListViewHeader(Context context) {
super(context);
initView(context);
} /**
* @param context
* @param attrs
*/
public XListViewHeader(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
} private void initView(Context context) {
// 初始情况,设置下拉刷新view高度
LayoutParams lp = new LayoutParams(
LayoutParams.MATCH_PARENT, 0);
mContainer = (LinearLayout) LayoutInflater.from(context).inflate(
R.layout.xlistview_header, null);
addView(mContainer, lp);
setGravity(Gravity.BOTTOM); mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow);
mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview);
mPBAnimation = AnimationUtils.loadAnimation(context, R.anim.loadmore);
LinearInterpolator lin = new LinearInterpolator();
mPBAnimation.setInterpolator(lin); mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
if (isInEditMode()) {
return;
}
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);
} public void setState(int state) {
if (state == mState)
return ;
mArrowImageView.clearAnimation();
if (state == STATE_REFRESHING) { // 显示进度
mArrowImageView.setImageResource(R.drawable.icon_loading_selected);
mArrowImageView.startAnimation(mPBAnimation);
} else { // 显示箭头图片
mArrowImageView.setImageResource(R.drawable.xlistview_arrow);
} switch(state){
case STATE_NORMAL:
if (mState == STATE_READY) {
mArrowImageView.startAnimation(mRotateDownAnim);
}
if (mState == STATE_REFRESHING) {
mArrowImageView.clearAnimation();
}
mHintTextView.setText(R.string.xlistview_header_hint_normal);
break;
case STATE_READY:
if (mState != STATE_READY) {
mArrowImageView.clearAnimation();
mArrowImageView.startAnimation(mRotateUpAnim);
mHintTextView.setText(R.string.xlistview_header_hint_ready);
}
break;
case STATE_REFRESHING:
mHintTextView.setText(R.string.xlistview_header_hint_loading);
break;
}
mState = state;
} public void setVisiableHeight(int height) {
if (height < 0)
height = 0;
LayoutParams lp = (LayoutParams) mContainer
.getLayoutParams();
lp.height = height;
mContainer.setLayoutParams(lp);
} public int getVisiableHeight() {
return mContainer.getHeight();
} }
package com.loaderman.androiddemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message; import java.util.ArrayList;
import java.util.List; public class MainActivity extends Activity implements XListView.IXListViewListener { protected static final int REFRESHING = 0;
protected static final int LOADMOREING = 1;
private XListView lv;
private List<String> data;
private TextAdapter adapter; private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REFRESHING:
for (int i = 0; i < 5; i++) {
data.add(0, "pre" + String.valueOf(i));
}
lv.stopRefresh();
break;
case LOADMOREING:
for (int i = 0; i < 5; i++) {
data.add(String.valueOf(data.size() + i));
}
lv.stopLoadMore();
break;
}
if (adapter!=null) {
adapter.setData(data);
adapter.notifyDataSetChanged();
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
adapter = new TextAdapter(MainActivity.this, data);
lv.setAdapter(adapter);
} private void initView() {
lv = (XListView) findViewById(R.id.lv);
lv.setPullRefreshEnable(true);// 开启下拉刷新
lv.setPullLoadEnable(true);// 开启上滑加载更多
lv.setXListViewListener(MainActivity.this);// 设置监听器
} private void initData() {
data = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
data.add(String.valueOf(i));
}
} @Override
public void onRefresh() {
Message msg = Message.obtain();
msg.what = REFRESHING;
handler.sendMessageDelayed(msg, 2000);
} @Override
public void onLoadMore() {
Message msg = Message.obtain();
msg.what = LOADMOREING;
handler.sendMessageDelayed(msg, 2000);
}
}
package com.loaderman.androiddemo;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import java.util.List; public class TextAdapter extends BaseAdapter { private Context context;
private List<String> data; public TextAdapter(Context context, List<String> data){
this.context = context;
this.data = data;
} public void setData(List<String> data) {
this.data = data;
} @Override
public int getCount() {
return data.size();
} @Override
public Object getItem(int position) {
return data.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageHolder holder = null;
if(convertView != null && convertView instanceof LinearLayout){
holder = (ImageHolder) convertView.getTag();
}else{
convertView = View.inflate(context, R.layout.listview_item, null);
holder = new ImageHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.iv_listview_item);
holder.tvName = (TextView) convertView.findViewById(R.id.tv_listview_item_name);
convertView.setTag(holder);
}
holder.tvName.setText(data.get(position));
holder.icon.setTag(position);
return convertView;
} class ImageHolder{
public ImageView icon;
public TextView tvName;
}
}

xlistview_footer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" > <RelativeLayout
android:id="@+id/xlistview_footer_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" > <TextView
android:id="@+id/xlistview_footer_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/xlistview_footer_hint_normal" /> <ImageView
android:id="@+id/iv_load"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/xlistview_footer_hint_textview"
android:layout_alignTop="@id/xlistview_footer_hint_textview"
android:layout_centerInParent="true"
android:layout_marginRight="5dp"
android:layout_toLeftOf="@id/xlistview_footer_hint_textview"
android:scaleType="fitEnd"
android:src="@drawable/icon_loading_not_selected" />
</RelativeLayout> </LinearLayout>

xlistview_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#f2f2f2"
android:gravity="bottom" > <RelativeLayout
android:id="@+id/xlistview_header_content"
android:layout_width="fill_parent"
android:layout_height="60dp" > <LinearLayout
android:id="@+id/xlistview_header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical" > <TextView
android:id="@+id/xlistview_header_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/xlistview_header_hint_normal" /> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/xlistview_header_last_time"
android:textSize="12sp" /> <TextView
android:id="@+id/xlistview_header_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout> <ImageView
android:id="@+id/xlistview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-35dp"
android:src="@drawable/xlistview_arrow" />
</RelativeLayout> </LinearLayout>
<resources>
<string name="app_name">androiddemo</string>
<string name="xlistview_header_hint_normal">下拉刷新</string>
<string name="xlistview_header_last_time">上次更新时间:</string>
<string name="xlistview_footer_hint_ready">查看更多</string>
<string name="xlistview_footer_hint_normal">加载更多</string>
<string name="xlistview_header_hint_ready">松开刷新数据</string>
<string name="xlistview_header_hint_loading">正在加载···</string>
</resources>

anim/loadmore.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<rotate
android:duration="500"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:toDegrees="359" />
</set>

效果:

XListView实现上拉加载下拉刷新的更多相关文章

  1. Vue mint ui用在消息页面上拉加载下拉刷新loadmore 标记

    之前总结过一个页面存在多个下拉加载的处理方式,今天再来说一下在消息页面的上拉加载和下拉刷新,基本上每个app都会有消息页面,会遇到这个需求 需求:每次加载十条数据,上拉加载下拉刷新,并且没有点击查看过 ...

  2. 上拉加载下拉刷新控件WaterRefreshLoadMoreView

    上拉加载下拉刷新控件WaterRefreshLoadMoreView 效果: 源码: // // SRSlimeView // @author SR // Modified by JunHan on ...

  3. RecyclerView 上拉加载下拉刷新

    RecyclerView 上拉加载下拉刷新 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/teach_s ...

  4. APICloud上啦加载下拉刷新模块

    apicloud有自带的上啦加载下拉刷新,当让也可以用第三方或者在模块库里面找一个使用 一.下拉刷新,一下代码写在 apiready = function (){} 里面 apiready = fun ...

  5. 微信小程序上拉加载下拉刷新

    微信小程序实现上拉加载下拉刷新 使用小程序默认提供方法. (1). 在xxx.json 中开启下拉刷新,需要设置backgroundColor,或者是backgroundTextStyle ,因为加载 ...

  6. mui scroll和上拉加载/下拉刷新

    mui中 scroll和上拉加载/下拉刷新同时存在会出现两个滚动条 把/*   */ /* //mui页面鼠标拖动代码: mui('.mui-scroll-wrapper').scroll({ dec ...

  7. SwipeRefreshLayout实现上拉加载下拉刷新

    package com.example.swiperefreshlayoutdemo; import java.util.ArrayList;import java.util.HashMap; imp ...

  8. zepto.js + iscroll.js上拉加载 下拉加载的 移动端 新闻列表页面

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

  9. MJRefresh(上拉加载下拉刷新)

    整理自:https://github.com/CoderMJLee/MJRefresh#%E6%94%AF%E6%8C%81%E5%93%AA%E4%BA%9B%E6%8E%A7%E4%BB%B6%E ...

随机推荐

  1. 使用redis事物解决stringRedisTemplate.setIfAbsent()并设置过期时间遇到的问题

    spring-date-redis版本:1.6.2场景:在使用setIfAbsent(key,value)时,想对key设置一个过期时间,同时需要用到setIfAbsent的返回值来指定之后的流程,所 ...

  2. Resource接口

    [转]https://blog.csdn.net/hbtj_1216/article/details/85487787 参考:官方文档 1 简介 Java标准库中的java.net.URL类和标准处理 ...

  3. android:duplicateParentState属性使用场景

    对于这个属性的使用也是在偶然的时候发现的,之前从未使用它,所以有必要阐述一下它的用法,什么场景会要用它这个属性,在我不知道之前这个属性之前,也同样能实现效果,但是当我知道它的存在之后,我肯定在某种场景 ...

  4. 分享私藏多年的Markdown编辑器

    相信很多人都使用 Markdown 来编写文章,Markdown 语法简洁,使用起来很是方便,而且各大平台几乎都已支持 Markdown 语法 那么,如何选择一款趁手的 Markdown 编辑器,就是 ...

  5. tomcate环境搭建

    Tomcat 环境搭建 最近在工作之余,看到了一些 Tomcat 的基础资料,感觉蛮好.同时也回忆起自己刚毕业要参加工作那会对 Tomcat 也是各种资料各种查,实属不易.为此,针对最近整理的一些基础 ...

  6. Scrapy框架的八个扩展

    一.proxies代理 首先需要在环境变量中设置 from scrapy.contrib.downloadermiddleware.httpproxy import HttpProxyMiddlewa ...

  7. @JsonSerialize @JsonIgnoreProperties @JsonIgnore @JsonFormat

    @JsonIgnoreProperties 此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响. @JsonIgnore 此注解用于属性或者方法上( ...

  8. learning scala pattern matching 02

    code package com.aura.scala.day01 object patternMatching02 { def main(args: Array[String]): Unit = { ...

  9. Linux文件系统属性权限chattr与lsattr命令

    有时候你发现用root权限都不能修改某个文件,大部分原因是曾经用chattr命令锁定该文件了.chattr命令的作用很大,其中一些功能是由Linux内核版本来支持的,不过现在生产绝大部分跑的linux ...

  10. 爬虫(五):PyQuery的使用

    一:简介 PyQuery库是jQuery的Python实现,可以用于解析HTML网页内容,是一个非常强大又灵活的网页解析库. -->官方文档地址 -->jQuery参考文档 二:初始化 初 ...