Android LinearLayout实现下拉刷新
来源:互联网 发布:淘宝毕业论文降重 编辑:程序博客网 时间:2024/06/05 20:58
效果图
实现思路
一般刷新给ListView
设置addHeaderView
,这里我们可以模仿着这种方式实现可刷新的LinearLayout
。然而LinearLayout
并没有提供addHeaderView
方法,既然不提供那么我们自己addView
添加第一个View
为我们下拉刷新的布局不就成了嘛。这里将添加的第一个View
称为HeadView
。初始化的时候隐藏HeadView
,然后重写onTouchEvent()
,实现自己的下拉刷新逻辑。如果想增加自己的一些动画,修改代码添加上动画的代码即可。开打!开打!
RefreshLinearLayout
的具体实现
/** * Created by dongyk on 2016/6/24. */public class RefreshLinearLayout extends LinearLayout { private final String TAG = this.getClass().getSimpleName(); private Context mContext; private View mHeadView; private TextView mTv; private int mHeadViewHeight = 50;//单位dp private int mStartX; private int mStartY; private int mEndX; private int mEndY; private int dx; private int dy; /** * 是否正在刷新标志位 */ private boolean isRefresh; public RefreshLinearLayout(Context context) { this(context,null); } public RefreshLinearLayout(Context context, AttributeSet attrs) { this(context, attrs,0); } public RefreshLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; forceVertival(); addHeadView(); onComplete(); } /** * 强制设置垂直方向 */ private void forceVertival() { if (getOrientation() == LinearLayout.HORIZONTAL){ setOrientation(LinearLayout.VERTICAL); } } /** * 增加头布局文件 */ private void addHeadView() { LayoutInflater inflater = LayoutInflater.from(mContext); mHeadView = inflater.inflate(R.layout.head_refresh_linearlayout,null); mHeadViewHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) mHeadViewHeight, mContext.getResources().getDisplayMetrics()); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mHeadViewHeight); mHeadView.setLayoutParams(params); this.addView(mHeadView); mTv = (TextView)(mHeadView.findViewById(R.id.tv_head_refresh)); } /** * 隐藏HeadView */ public void onComplete(){ setHeadViewPaddingTop(mHeadViewHeight); } /** * * @param paddingTop 隐藏的高度 */ private void setHeadViewPaddingTop(int paddingTop){ if(paddingTop > mHeadViewHeight){ new IllegalArgumentException("paddingTop must < HeadViewHeight "); } setPadding(getPaddingLeft(),-paddingTop,getPaddingRight(),getPaddingBottom()); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mStartX = (int) event.getX(); mStartY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: mEndX = (int) event.getX(); mEndY = (int) event.getY(); dx = Math.abs(mEndX - mStartX); dy = mEndY - mStartY; if (0 < dy && dy < mHeadViewHeight && dy>dx){ setHeadViewPaddingTop(mHeadViewHeight - dy ); mTv.setText("下拉加载数据"); }else if(dy >= mHeadViewHeight && dy>dx){ setHeadViewPaddingTop(0); isRefresh = true; mTv.setText("松开即可刷新"); } break; case MotionEvent.ACTION_UP: if (isRefresh) { setHeadViewPaddingTop(0); mTv.setText("正在刷新"); if (mIRefreshListener != null){ mIRefreshListener.onStart(); mIRefreshListener.onLoading(); mIRefreshListener.onEnd(); } isRefresh = false; } else { onComplete(); } break; default: break; } return true; } private IRefreshListener mIRefreshListener; public interface IRefreshListener{ void onStart(); void onLoading(); void onEnd(); } public void setIRefreshListener(IRefreshListener mIRefreshListener) { this.mIRefreshListener = mIRefreshListener; }}
控件取名为RefreshLinearLayout
。可以看到RefreshLinearLayout
继承LinearLayout
。在三个互相调用的构造函数最后我们首先设置RefreshLinearLayout
的布局方向为VERTICAL
,如果是横向,应该是左滑刷新,下拉刷新难免太傻了点。之后填充HeadView
设置参数没撒好说的。花3s扫一下即可。紧接着调用了onComplete()
方法,在暴露的公共方法onComplete()
方法中调用setHeadViewPaddingTop()
参数为HeadView
的高mHeadViewHeight
。需要注意下这个方法。
/** * * @param paddingTop 隐藏的高度 */ private void setHeadViewPaddingTop(int paddingTop){ if(paddingTop > mHeadViewHeight){ new IllegalArgumentException("paddingTop must < HeadViewHeight "); } setPadding(getPaddingLeft(),-paddingTop,getPaddingRight(),getPaddingBottom()); }
可以看到setHeadViewPaddingTop()
中仅仅调用了setPadding()
方法。
setPadding(getPaddingLeft(),-paddingTop,getPaddingRight(),getPaddingBottom());
由于下拉刷新的存在,所以这里禁止了布局文件中android:paddingTop=""
的属性。而且在paddingTop
的位置,设置的是参数的负值。正常设置padding
是正值,因此产生内容和控件的距离。如果padding
是负值,那么显示效果为内容大于控件,多余部分则会被隐藏。由于给setHeadViewPaddingTop()
传递的参数为HeadViewHeight
,因此实现了隐藏HeadView
的效果。
然后再onTouchEvent()
中随着手势不断改变HeadView
隐藏的高度,即可达到下拉刷新的效果。在ACTION_UP
中根据标志位isRefresh
判断是否执行相应的操作。为此还需要一些回调方法,这里统一写在IRefreshListener
接口中。
private IRefreshListener mIRefreshListener; public interface IRefreshListener{ void onStart(); void onLoading(); void onEnd(); } public void setIRefreshListener(IRefreshListener mIRefreshListener) { this.mIRefreshListener = mIRefreshListener; }
在ACTION_UP
中依次调用了onStart()
、onLoading()
和onEnd()
方法。除此之外,还暴露了一个onComplete()
方法,用于收起HeadView
。至此,RefreshLinearLayout分析完毕。下面看个简单实现的Demo。
运用示例
private void initRefreshListener() { ll_refresh.setIRefreshListener(new RefreshLinearLayout.IRefreshListener() { @Override public void onStart() { Log.i("RefreshLinearLayout", "onStart"); tv.setText("onStart"); } @Override public void onLoading() { Log.i("RefreshLinearLayout", "onLoading"); tv.setText("onLoading"); getNetWorkData(); } @Override public void onEnd() { tv.setText("onEnd"); Log.i("RefreshLinearLayout", "onEnd"); } }); } /** * 模拟网络获取数据 */ private void getNetWorkData(){ new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2*1000); myHandler.sendEmptyMessage(EMPTY_MSG); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } private MyHandler myHandler; class MyHandler extends Handler{ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == EMPTY_MSG){ ll_refresh.onComplete(); } } }
在onLoading()
中执行getNetWorkData()
方法模拟网络请求,在Handler中调用onComplete()
方法收起HeadView
。这里的Handler可能会造成内存泄露,完善点可以在onDestroy()
中添加myHandler.removeCallbacksAndMessages(null)
。感兴趣可以详见内存泄露简介、典型情景及检测解决。
- Android LinearLayout实现下拉刷新
- Android下拉刷新实现
- Android中实现下拉刷新
- Android中实现下拉刷新 .
- Android中实现下拉刷新
- Android中实现下拉刷新
- Android中实现下拉刷新
- Android中实现下拉刷新
- Android中实现下拉刷新
- Android中实现下拉刷新 .
- android 下拉刷新 快速实现
- Android 下拉刷新框架实现
- Android 下拉刷新框架实现
- Android 下拉刷新框架实现
- Android 下拉刷新框架实现
- Android下拉刷新ListView实现
- Android 下拉刷新框架实现
- Android 下拉刷新框架实现
- 学会识别数据线!真的有必要!
- iOS软件开发获取相机图片处理
- 单片机开发交叉编译
- 【WIN32】IntelliSense: "const char *" 类型的实参与 "LPCWSTR" 类型的形参不兼容
- 虚拟现实-VR-UE4-LEAP-Motion手势识别
- Android LinearLayout实现下拉刷新
- fopen()
- GIS离线地图瓦片的生成及发布
- Android应用开发之(通过ClipboardManager, ClipData进行复制粘贴)
- android 设置系统屏幕亮度
- R把科学计数法表示的数字转化为文本
- Linux下重启tomcat
- iOS开发之单元测试/Unit Tests
- Leetcode no. 347