安卓 relativelayout5.0 SwipeRefreshLayout里面怎么不能嵌套布局

谢邀。本来在onCreate里面调用SwipeRefreshLayout.setRefreshing(ture,true)即可,但是,这个Api是私有的。所以只能用反射或者手动调SwipeRefreshLayout.setRefreshing(true)+RefreshLayout.OnRefreshListener.onRefresh方法。反射代码如下:public static void setRefreshing(SwipeRefreshLayout refreshLayout,boolean refreshing, boolean notify){
Class&? extends SwipeRefreshLayout& refreshLayoutClass = refreshLayout.getClass();
if (refreshLayoutClass != null) {
Method setRefreshing = refreshLayoutClass.getDeclaredMethod("setRefreshing", boolean.class, boolean.class);
setRefreshing.setAccessible(true);
setRefreshing.invoke(refreshLayout, refreshing, notify);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
然后调用setRefreshing(mRefreshLayout,true,true)即可。反射请在Proguard里面屏蔽掉setRefreshing,代码如下
-keepclassmembers android.support.v4.widget.SwipeRefreshLayout{
private void setRefreshing(boolean,boolean);
以上两种方法注意进行延时(应该算是一个bug吧),参考
提供的方式 。知乎会自动缓存第一页HTTP数据,每次打开时会把缓存先展示出来,然后再去接口请求数据,同时设置SwipeRefreshLayout的自动刷新,数据到了,把缓存替换掉,同时设置SwipeRefreshLayout.setRefreshing(false)。
看了几个回答,都没有回答到点子上,走了弯路.先解释下为什么setRefreshing没有作用
public void setRefreshing(boolean refreshing) {
if (refreshing && mRefreshing != refreshing) {
// scale and show
mRefreshing =
int endTarget = 0;
if (!mUsingCustomStart) {
endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop);
endTarget = (int) mSpinnerFinalO
setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,
true /* requires update */);
startScaleUpAnimation(mRefreshListener);
setRefreshing(refreshing, false /* notify */);
} 在onCreate里或onCreateView里调用setRefreshing,这个时候关键变量mOriginalOffsetTop并没有获取正确的值。下拉效果动画过程中没有显示到正确的坐标,我们看看这个值是什么时候获取的,上代码
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mTarget == null) {
ensureTarget();
if (mTarget == null) {
mTarget.measure(MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
mOriginalOffsetCalculated =mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
mCircleViewIndex = -1;
// Get the index of the circleview.
for (int index = 0; index & getChildCount(); index++) {
if (getChildAt(index) == mCircleView) {
mCircleViewIndex =
} 如代码所见,是在onMeasure里获取的,根据CircleView的高度来赋值的。所以要解决的方法是让mOriginalOffsetTop能在setRefreshing前正确赋值。比较笨的方法是在onCreate里或onCreateView手动赋值,不推荐。正确做法是在onMeasure触发后再调用setRefreshing。代码如下:
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mRefreshLayout.setRefreshing(true);
loadData(true);
}); 其它的下拉刷新库也有类似问题,关键变量需要在onMeasure里获取。也无法显示到正确的位置。类似其它自定义控件需要在控件没有度量好,先调用涉及到相关变量的方法,都可以类似解决。
回家写 mark 20:40 更新首先想要在界面一加载的时候出现更新效果,直接调用setRfreshing(true)是出不来效果的,这个问题我以前也遇到过,必须调用 SwipeRefreshLayout.post(new Runable(){
public void run() {
SwipeRefreshLayout.setRefreshing(true);
}});关闭的时候也使用SwipeRefreshLayout.post(new Runable(){
public void run() {
SwipeRefreshLayout.setRefreshing(false);
}});但是如果你认为这样就会走onRefresh方法,那你就大错特错了,setRefreshing(true)是不会触发onRefresh的,必须要手动调用一次所以在界面onCreate里面想要立刻加载就需要这样SwipeRefreshLayout.post(new Runable(){
public void run() {
SwipeRefreshLayout.setRefreshing(true);
}});onRefresh(); 21:55 更新初始化:OnRefreshListener listener = new OnRefreshListener(){
public void onRefresh(){
SwipeRefreshLayout mSRLayout = (SwipeRefreshLayout) findviewbyId(R.id.layout);
mSRLayout.setOnRefreshListener(listener);
onCreate中:mSRLayout.post(new Runable(){
public void run() {
SwipeRefreshLayout.setRefreshing(true);
listener.onRefresh()
Android开发工程师@搜狗谷歌官方下拉刷新控件 SwipeRefreshLayoutDemo - PullToRefresh|安卓源码|自定义控件 - 安卓序 | ApkDemo
240 次浏览 |
文章目录SwipeRefreshLayoutDemo
SwipeRefreshLayout demo (Google官方下拉刷新组件)
网站声明:ApkDemo是一个免费的开源分享网站,所有源代码皆由网络收集并发布在ApkDemo,任何人都可以免费使用和分享ApkDemo。请支持ApkDemo(留言支持、把ApkDemo分享给你的小伙伴、捐赠ApkDemo)。代码如诗。
听一听每天轻松音乐
选择分类目录
2014经典文章&&(3)
ApkDemo官方通告&&(6)
安卓源码&&(129)
&&&动画源码&&(15)
&&&应用源码&&(5)
&&&开源工具类&&(1)
&&&游戏源码&&(1)
&&&第三方开源框架&&(11)
&&&自定义控件&&(91)
&&&&&&Button&&(1)
&&&&&&Dialog&&(5)
&&&&&&GridView&&(4)
&&&&&&ListView&&(18)
&&&&&&Menu&&(6)
&&&&&&Progress&&(4)
&&&&&&progressbar&&(7)
&&&&&&PullToRefresh&&(5)
&&&&&&ScrollView&&(4)
&&&&&&SeekBar&&(1)
&&&&&&Textview&&(3)
&&&&&&Toast&&(1)
&&&&&&ViewPage&&(8)
&&&&&&WheelView&&(2)
&&&&&&变形控件&&(1)
&&&&&&图形表图&&(1)
&&&&&&按钮开关&&(7)
&&&&&&日历控件&&(2)
&&&蓝牙例子&&(2)
&&&蓝牙源码&&(2)
&&&蓝牙聊天源码&&(1)
&&&进度条&&(6)
&&&通讯录&&(1)
截图控件&&(2)
站长推荐(自家用)&&(12)SwipeRefreshLayout和ListView的EmptyView共存冲突的问题 - 短裤党 - ITeye技术网站
博客分类:
SwipeRefreshLayout是android官方的下拉刷新控件;
它内部有且只能有一个子控件;
当一个ListView嵌入到它内部时,就不能为ListView带一个EmptyView了;
于是很自然的想到将ListView和EmptyView纳入到一个父控件中;
典型的像下面这样的布局:
&android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" &
&FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" &
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:divider="@color/text_color_c4"
android:dividerHeight="@dimen/line_width"
android:footerDividersEnabled="true" /&
android:id="@+id/emptyView"
layout="@layout/empty_view_for_tang_friend_0" /&
&/FrameLayout&
&/android.support.v4.widget.SwipeRefreshLayout&
这样就可以实现ListView和EmptyView都下拉刷新了;
但是问题来了,当ListView的数据超过一屏的时候,再往上滑,滑不上去了;
这就是SwipeRefreshLayout和ListView的EmptyView共存冲突的问题(如果SwipeRefreshLayout中仅有一个ListView的话没问题,但现在多了一个EmptyView);
解决办法有是有,虽然不那么优雅:
swipeRefreshLayout = (android.support.v4.widget.SwipeRefreshLayout) v.findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setColorSchemeResources(R.color.text_color_c6, R.color.yellow, R.color.grey, R.color.red);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
public void onRefresh()
// TODO Auto-generated method stub
//dosomething
listView = (ListView) v.findViewById(R.id.listView);
listView.setOnScrollListener(new AbsListView.OnScrollListener()
public void onScrollStateChanged(AbsListView absListView, int i)
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount)
if (firstVisibleItem == 0)
swipeRefreshLayout.setEnabled(true);
swipeRefreshLayout.setEnabled(false);
在ListView滑动的时候做一个判断,看看是不是滑动到顶部了,到顶部了就swipeRefreshLayout.setEnabled(true);让SwipeRefreshLayout可以接受动作,这样就ok了。
上面的解决方案比较简单,但是有个小问题,就是当listView滑动到第一个Item(让第一个Item显示一半)的时候,再上滑就上不去了,始终显示半个Item。
为了解决这个问题,只能使用笨办法了:将ListView和EmptyView分离,让他们两个分别被两个SwipeRefreshLayout包裹,如下面的布局:
&?xml version="1.0" encoding="utf-8"?&
&FrameLayout xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" &
&android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" &
&cn.tangdada.tangbang.widget.LoadMoreListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:divider="@color/text_color_c4"
android:dividerHeight="@dimen/line_width"
android:footerDividersEnabled="false" /&
&/android.support.v4.widget.SwipeRefreshLayout&
&android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayoutEmptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" &
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:text="@string/empty"
android:textColor="@color/text_color_c3"
android:textSize="@dimen/font_big" /&
&/android.support.v4.widget.SwipeRefreshLayout&
&/FrameLayout&
然后需要在代码中控制显示EmptyView的时机,比如我这里的:
private void updateViews(Object obj)
ArrayList&User& list = (ArrayList&User&)
if (list.size() == 0)
//listView.removeLoadMoreListener();
users.addAll(list);
if (users.size() == 0)
swipeRefreshLayout.setVisibility(View.GONE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayoutEmptyView.setVisibility(View.VISIBLE);
swipeRefreshLayoutEmptyView.setRefreshing(false);
//listView.onLoadMoreComplete();
swipeRefreshLayout.setVisibility(View.VISIBLE);
swipeRefreshLayout.setRefreshing(false);
swipeRefreshLayoutEmptyView.setVisibility(View.GONE);
swipeRefreshLayoutEmptyView.setRefreshing(false);
notifyDataSetChanged();
SwipeRefreshLayout完美添加及完善上拉加载功能
android-Ultra-Pull-To-Refresh 源码解析
gundumw100
浏览: 2681279 次
来自: 上海
感谢楼主分享,正好解决了我的问题。不过发现,重写ViewPag ...
一级苦工 写道弱弱的问一句,第一种方法能监听到用户是否点击发送 ...
弱弱的问一句,第一种方法能监听到用户是否点击发送按钮并成功发送 ...
楼主牛叉。

我要回帖

更多关于 安卓layout布局 的文章

 

随机推荐