Closed dahai2070 closed 4 years ago
之前的1.6.6.8 是没有问题的。
@dahai2070 不是很明白失效是什么意思,这边布局相关代码是没有修改的,另外我测试了发现没有问题。
失效是指上拉加载和下拉刷新,recyclerView 滑动到上下极限后,refreshLayout 都没有反应了。
日志没没看到报错,是有日志控制开关吗?
@dahai2070 NestedScrollView
嵌套RecyclerView
的话是和#101一样的问题,不能设置RecyclerView
的setHasFixedSize(true)
或者必须手动requestLayout
。如果不是NestedScrollView
嵌套RecyclerView
,我也测试了没有问题
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent">
<me.dkzwm.widget.srl.MaterialSmoothRefreshLayout
android:id="@+id/smoothRefreshLayout_with_textView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#E8E8E8"
android:gravity="center"
android:text="@string/with_textView"
android:textColor="#333333"
android:textSize="28sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#E8E8E8"
android:gravity="center"
android:text="@string/with_textView"
android:textColor="#333333"
android:textSize="28sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#E8E8E8"
android:gravity="center"
android:text="@string/with_textView"
android:textColor="#333333"
android:textSize="28sp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</me.dkzwm.widget.srl.MaterialSmoothRefreshLayout>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
package me.dkzwm.widget.srl.sample.ui;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import me.dkzwm.widget.srl.RefreshingListenerAdapter;
import me.dkzwm.widget.srl.SmoothRefreshLayout;
import me.dkzwm.widget.srl.sample.R;
/**
* Created by dkzwm on 2017/6/1.
*
* @author dkzwm
*/
public class WithTextViewActivity extends AppCompatActivity {
private SmoothRefreshLayout mRefreshLayout;
private Handler mHandler = new Handler();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_with_textview);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle(R.string.with_textView);
mRefreshLayout = findViewById(R.id.smoothRefreshLayout_with_textView);
mRefreshLayout.setEnableKeepRefreshView(true);
mRefreshLayout.setDisableLoadMore(false);
mRefreshLayout.setOnRefreshListener(
new RefreshingListenerAdapter() {
@Override
public void onRefreshing() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
mRefreshLayout.refreshComplete();
}
},
2000);
}
@Override
public void onLoadingMore() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
mRefreshLayout.refreshComplete();
}
},
2000);
}
});
mRefreshLayout.autoRefresh(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
startActivity(new Intent(WithTextViewActivity.this, MainActivity.class));
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
如上代码运行良好
@dahai2070 你的具体是什么样子的,内部是否像 #101 一样的布局,如果是你使用 #101 我贴出代码和布局测试是没有问题的。我不是很清楚内部是什么布局,看Log定位不到问题的
NestedScrollView 中确实有个布局,是recyclerView , 我不折腾了,我继续用之前的版本。
@dahai2070 如果老版本真没这种情况也可以,但布局相关代码是一致的,理论上不存在新版本不可以,应该就是RecyclerView
的setHasFixedSize(true)
导致的问题
去看了下代码, 没有设置 setHasFixedSize(true), 但是设置了 setNestedScrollingEnabled(false);
@dahai2070 这边能麻烦将setNestedScrollingEnabled(false)
代码移入xml中吗,至少从你发的log中得知关闭代码没有起作用
这样吗?
刚才给你发的日子上拉 下拉日志,是这个页面的,非常简单的页面
这是一个fragment,所在的activity 使用了 CoordinatorLayout
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent">
<me.dkzwm.widget.srl.MaterialSmoothRefreshLayout
android:id="@+id/smoothRefreshLayout_with_textView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#E8E8E8"
android:gravity="center"
android:text="@string/with_textView"
android:textColor="#333333"
android:textSize="28sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_with_testView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</me.dkzwm.widget.srl.MaterialSmoothRefreshLayout>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
package me.dkzwm.widget.srl.sample.ui;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
import java.util.List;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.dkzwm.widget.srl.RefreshingListenerAdapter;
import me.dkzwm.widget.srl.SmoothRefreshLayout;
import me.dkzwm.widget.srl.sample.R;
import me.dkzwm.widget.srl.sample.adapter.RecyclerViewAdapter;
import me.dkzwm.widget.srl.sample.utils.DataUtil;
/**
* Created by dkzwm on 2017/6/1.
*
* @author dkzwm
*/
public class WithTextViewActivity extends AppCompatActivity {
private SmoothRefreshLayout mRefreshLayout;
private Handler mHandler = new Handler();
private RecyclerView mRecyclerView;
private RecyclerViewAdapter mAdapter;
private int mCount;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_with_textview);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle(R.string.with_textView);
mRecyclerView = findViewById(R.id.recyclerView_with_testView);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mAdapter = new RecyclerViewAdapter(this, getLayoutInflater());
mRecyclerView.setAdapter(mAdapter);
mRefreshLayout = findViewById(R.id.smoothRefreshLayout_with_textView);
mRefreshLayout.setDisableLoadMore(false);
mRefreshLayout.setOnRefreshListener(
new RefreshingListenerAdapter() {
@Override
public void onRefreshing() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
List<String> list = DataUtil.createList(mCount, 60);
mCount = list.size();
mAdapter.insertData(list);
mRefreshLayout.refreshComplete();
}
},
2000);
}
@Override
public void onLoadingMore() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
List<String> list = DataUtil.createList(mCount, 15);
mCount += list.size();
mAdapter.appendData(list);
mRefreshLayout.refreshComplete();
}
},
2000);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
startActivity(new Intent(WithTextViewActivity.this, MainActivity.class));
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
以上是我写的测试代码,和你的布局基本一致
接下来,我吃了晚饭,再给你发 activity 里面的日志。
嗯。你发的这个页面,和我activity 里面的布局很接近,不过我有一个View 使用了 app:layout_behavior="@string/bottom_sheet_behavior"
吃饭去了,,吃了饭,我给你发日子,这个activity的日志
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<me.dkzwm.widget.srl.MaterialSmoothRefreshLayout
android:id="@+id/smoothRefreshLayout_with_textView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#E8E8E8"
android:gravity="center"
android:text="@string/with_textView"
android:textColor="#333333"
android:textSize="28sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_with_testView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</me.dkzwm.widget.srl.MaterialSmoothRefreshLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/linearLayout_with_testView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="40dp"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/colorPrimary"
android:text="测试"
android:textColor="@android:color/white"
android:textSize="18sp" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
package me.dkzwm.widget.srl.sample.ui;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.LinearLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import java.util.List;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.dkzwm.widget.srl.RefreshingListenerAdapter;
import me.dkzwm.widget.srl.SmoothRefreshLayout;
import me.dkzwm.widget.srl.sample.R;
import me.dkzwm.widget.srl.sample.adapter.RecyclerViewAdapter;
import me.dkzwm.widget.srl.sample.utils.DataUtil;
/**
* Created by dkzwm on 2017/6/1.
*
* @author dkzwm
*/
public class WithTextViewActivity extends AppCompatActivity {
private SmoothRefreshLayout mRefreshLayout;
private Handler mHandler = new Handler();
private RecyclerView mRecyclerView;
private RecyclerViewAdapter mAdapter;
private int mCount;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_with_textview);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle(R.string.with_textView);
mRecyclerView = findViewById(R.id.recyclerView_with_testView);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
mAdapter = new RecyclerViewAdapter(this, getLayoutInflater());
mRecyclerView.setAdapter(mAdapter);
mRefreshLayout = findViewById(R.id.smoothRefreshLayout_with_textView);
mRefreshLayout.setDisableLoadMore(false);
mRefreshLayout.setOnRefreshListener(
new RefreshingListenerAdapter() {
@Override
public void onRefreshing() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
List<String> list = DataUtil.createList(mCount, 60);
mCount = list.size();
mAdapter.insertData(list);
mRefreshLayout.refreshComplete();
}
},
2000);
}
@Override
public void onLoadingMore() {
mHandler.postDelayed(
new Runnable() {
@Override
public void run() {
List<String> list = DataUtil.createList(mCount, 15);
mCount += list.size();
mAdapter.appendData(list);
mRefreshLayout.refreshComplete();
}
},
2000);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
case Menu.FIRST:
LinearLayout linearLayout = findViewById(R.id.linearLayout_with_testView);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(linearLayout);
if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, "展开/收缩");
return super.onCreateOptionsMenu(menu);
}
@Override
public void onBackPressed() {
startActivity(new Intent(WithTextViewActivity.this, MainActivity.class));
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
测试没有问题
dahai2070 这边跟踪日志,你是否嵌套有自定义视图且实现了NestedScrollingParent2
以下接口,从1.7.0.androidx
开始,SRL是实现了NestedScrollingParent3
接口的,需配合实现了NestedScrollingParent3
接口的视图才能正确工作,由于向下兼容的问题,ViewParentCompat
在onNestedScroll
方法中将实现低于NestedScrollingParent2
的视图时选择将未消耗量直接传递给了消耗量,导致consumed
拿到的值等于dyUnconsumed/dxUnconsumed。传递到SRL层时,SRL发现两值相等表示已完成消耗故而不会做任何操作
有嵌套自定义视图,刚才去 搜了下,没有实现 NestedScrollingParent 相关的接口。
@dahai2070 你可以尝试跟踪下
@Override
public void onNestedScroll(
@NonNull View target,
int dxConsumed,
int dyConsumed,
int dxUnconsumed,
int dyUnconsumed,
int type,
@NonNull int[] consumed) {
// 此处Debug下
dispatchNestedScroll(
dxConsumed,
dyConsumed,
dxUnconsumed,
dyUnconsumed,
mParentOffsetInWindow,
type,
consumed);
打下断点,跟踪下日志,看是哪一个视图的问题
最终会走到ViewParentCompat
的
public static void onNestedScroll(ViewParent parent, View target, int dxConsumed,
int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type,
@NonNull int[] consumed) {
if (parent instanceof NestedScrollingParent3) {
((NestedScrollingParent3) parent).onNestedScroll(target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, type, consumed);
} else {
// If we are calling anything less than NestedScrollingParent3, add the unconsumed
// distances to the consumed parameter so calling NestedScrollingChild3 implementations
// are told the entire scroll distance was consumed (for backwards compat).
consumed[0] += dxUnconsumed;
consumed[1] += dyUnconsumed;
if (parent instanceof NestedScrollingParent2) {
((NestedScrollingParent2) parent).onNestedScroll(target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, type);
} else if (type == ViewCompat.TYPE_TOUCH) {
// Else if the type is the default (touch), try the NestedScrollingParent API
if (Build.VERSION.SDK_INT >= 21) {
try {
parent.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed);
} catch (AbstractMethodError e) {
Log.e(TAG, "ViewParent " + parent + " does not implement interface "
+ "method onNestedScroll", e);
}
} else if (parent instanceof NestedScrollingParent) {
((NestedScrollingParent) parent).onNestedScroll(target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed);
}
}
}
}
问题可能出在
if (Build.VERSION.SDK_INT >= 21) {
try {
parent.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed);
} catch (AbstractMethodError e) {
Log.e(TAG, "ViewParent " + parent + " does not implement interface "
+ "method onNestedScroll", e);
}
} else if (parent instanceof NestedScrollingParent) {
((NestedScrollingParent) parent).onNestedScroll(target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed);
}
嗯,空了再学习,测试下,sml里面代码很多,也许我一时半会找不到问题所在,我现在暂且用1.6.**。
根源可能是有自定义没有正确实现NestedScrolling
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return false;//此处返回了true
}
也有可能是自定义视图只实现了NestedScrollingParent2
及以下接口。在onStartNestedScroll
返回true
视图并完整实现了NestedScrollingParent3
情况下,SRL工作得都挺好
不知道是不是 我对NestedScrollView 设置了监听的缘故,仅仅是猜测