Android兼容性优化-Android M以下兼容ScrollView.setOnScrollChangeListener() 方案
崩溃日志:
java.lang.NoClassDefFoundError
12-08 13:47:58.781 8872 8872 W dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41a72ce0)
6512-08 13:47:58.781 8872 8872 W dalvikvm: threadid=1: uncaught exception occurred
6612-08 13:47:58.781 8872 8872 W System.err: java.lang.NoClassDefFoundError: com.pxwx.curricula.CurriculaFragment$c
6712-08 13:47:58.782 8872 8872 W System.err: at com.pxwx.curricula.CurriculaFragment.initView()
6812-08 13:47:58.782 8872 8872 W System.err: at com.pxwx.curricula.CurriculaFragment.onViewCreated()
6912-08 13:47:58.782 8872 8872 W System.err: at androidx.fragment.app.FragmentStateManager.createView()
抛出异常信息:
java.lang.NoClassDefFoundError
定位出错位置initView方法:
针对ScrollView.setOnScrollChangeListener()方法添加了如下注解
@RequiresApi(api = Build.VERSION_CODES.M)
以上注解表示注解目标只能够在指定的版本API及以上运行,消除高版本Api在低版本SDK上的报错。
注:慎用@RequiresApi等注解消除高版本Api在低版本SDK上的报错,容易出现版本兼容问题
@RequiresApi(api = Build.VERSION_CODES.M)
private void initView() {
//初始化滑动联动toolbar
nsv.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (scrollY < SCROLL_DISTANCE) {//隐藏toolbar
if (scrollY < SCROLL_MINHEIGHT){
toolbar.set(View.GONE);
toolbarTitle.set(View.GONE);
toolbarTitleAlpha.set(0f);
}else{
toolbar.set(View.VISIBLE);
//标题栏的渐变
toolbarBackColor.set(changeAlpha(UIUtils.getColor(R.color.white)
, scrollY / SCROLL_DISTANCE));
toolbarTitleAlpha.set(scrollY / SCROLL_DISTANCE);
toolbarTitle.set(View.VISIBLE);
}
}else{
toolbar.set(View.VISIBLE);
toolbarTitle.set(View.VISIBLE);
toolbarTitleAlpha.set(1.0f);
toolbarBackColor.set(UIUtils.getColor(R.color.white));
}
}
});
根据如上分析,导致 java.lang.NoClassDefFoundError异常是因为运行在了sdk低于23的版本上手机上导致的。
解决方法:
如下解决ScrollView.setOnScrollChangeListener() 在23以下兼容可用;
可以通过实现NestedScrollView并复写它的onScrollChanged方法自定义监听,具体代码如下:
/**
* 修复setOnScrollChangeListener不兼容M以下版本
*/
//1、定义NormalScorllVIew并集成NestedScrollView
public class NormalScorllVIew extends NestedScrollView {
private OnScrollChanged mOnScrollChanged;
public NormalScorllVIew(@NonNull Context context) {
super(context);
}
public NormalScorllVIew(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public NormalScorllVIew(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//2、复写onScrollChanged方法
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//5、通过接口执行自身的滑动监听
if (mOnScrollChanged != null)
mOnScrollChanged.onScroll(l, t, oldl, oldt);
}
//4、给义NormalScorllVIew添加接口监听
public void setOnScrollChanged(OnScrollChanged onScrollChanged){
this.mOnScrollChanged = onScrollChanged;
}
//3、定义自定义接口,暴露onScroll方法
public interface OnScrollChanged{
void onScroll(int l, int t, int oldl, int oldt);
}
}
外面实现自定义的接口,自定义ScrollView设置接口监听,复写onScroll方法,监听滑动
//1、实现自定义的接口
xxx implements NormalScorllVIew.OnScrollChanged
//2自定义ScrollView设置接口监听
nsv.setOnScrollChanged(this);
//3、复写onScroll方法
@Override
public void onScroll(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
//4、监听滑动
if (scrollY < SCROLL_DISTANCE) {//隐藏toolbar
if (scrollY < SCROLL_MINHEIGHT){
toolbar.set(View.GONE);
toolbarTitle.set(View.GONE);
toolbarTitleAlpha.set(0f);
}else{
toolbar.set(View.VISIBLE);
//标题栏的渐变
toolbarBackColor.set(viewModel.changeAlpha(UIUtils.getColor(R.color.white)
, scrollY / SCROLL_DISTANCE));
toolbarTitleAlpha.set(scrollY / SCROLL_DISTANCE);
toolbarTitle.set(View.VISIBLE);
}
}else{
toolbar.set(View.VISIBLE);
toolbarTitle.set(View.VISIBLE);
toolbarTitleAlpha.set(1.0f);
toolbarBackColor.set(UIUtils.getColor(R.color.white));
}
}
< END >
【Android进化之路】
微信扫描二维码,关注我的公众号。