Android日常问题记录

1.Message 创建应该使用obtain()方法,而不应该使用 new

当我们调用Message.obtain()方法时,如果复用池中存在Message对象,我们就不会去创建一个新的Message对象。这样就避免了频繁创建和销毁Messgae对象的带来的性能开销。

2.在电脑上拦截模拟器请求

1.首先先设置号模拟器上的代理模式,WIFI里面有个修改网络,里面有个代理,打开后选择打开
代理服务器主机名填你使用的电脑IP地址,代理服务端口填你要监听的app连接后台的端口保存就好了

3.Android 下拉通知栏时Activity的生命周期

下拉通知栏对生命周期是没有什么影响的

4.Activity的四种启动模式launchMode的区别

  1. standard
    standard模式是默认的启动模式,不用为配置android:launchMode属性即可,当然也可以指定值为standard。

  2. singleTop
    在上面的基础上为指定属性android:launchMode=“singleTop”,系统就会按照singleTop启动模式处理跳转行为。singleTop启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。

  3. singleTask
    在上面的基础上修改FActivity的属性android:launchMode=“singleTask”。singleTask模式,如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。

  4. singleInstance
    这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。

5.Activity 状态保存与恢复

有如下几种情况是需要对数据进行保存的
  1. 点击了返回键
  2. 锁屏
  3. 点击了Home键
  4. 有其他APP进入了前台(比如接电话)
  5. 启动新的Activity
  6. 屏幕发生了旋转
  7. App发生意外被杀死

首先是在onSaveInstanceState中保存数据
紧接着在onRestoreInstanceState对数据进行恢复

6.scrollview 加ListView组合嵌套 ListView只会出现一个条目

修改方法:重新测量ListView的高度
public void setListViewHeightBasedOnChildren(ListView listView) {
        // 获取ListView对应的Adapter
        android.widget.ListAdapter adapter = listView.getAdapter();
        if (adapter == null) {
            return;
        }

        int totalHeight = 0;
        for (int i = 0, len = adapter.getCount(); i < len; i++) {
            // listAdapter.getCount()返回数据项的数目
            View listItem = adapter.getView(i, null, listView);
            // 计算子项View 的宽高
            listItem.measure(0, 0);
            // 统计所有子项的总高度
            totalHeight += listItem.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight+ (listView.getDividerHeight() * (adapter.getCount() - 1));
        // listView.getDividerHeight()获取子项间分隔符占用的高度
        // params.height最后得到整个ListView完整显示需要的高度
        listView.setLayoutParams(params);
    }

7.Android事件分发机制

android的事件分发机制:开始是有我们点击手机屏幕的动作

动作作用
MotionEvent.ACTION_DOWN手指在手机屏幕按下
MotionEvent.ACTION_MOVE手指在手机屏幕移动
MotionEvent.ACTION_UP手指在手机屏幕抬起来
MotionEvent.ACTION_CANCEL因为异常原因,而退出当前操作的

image

手指按下屏幕后 事件最先进入的是Activity里面执行 dispatchTouchEvent方法

接着Activity通过dispatchTouchEvent方法把事件分发给ViewGroup层 的dispatchTouchEvent方法

ViewGroup层的dispatchTouchEvent方法有三个走向,return true—事件终结 return false—事件回溯给父类的onTouchEvent

还有一个调用super 就是调用 把事件给ViewGroup层的独有的onInterceptTouchEvent方法

就是问一问这个事件要不要留给自己来处理,如果return true的话 它就会把这个事件交给自己的onTouchEvent来处理, 如果return false 的话它就会往子控件那里面传。

传到子View后就遍历循环所有子View 如果没有的话就是回溯给父类,如果找到子View的话就消费

如果都没有的话就是一直往父类回溯,所以这个图大概是呈U形状的结构

最后总结一下 对于 dispatchTouchEvent,onTouchEvent,return true是终结事件传递。return false 是回溯到父View的onTouchEvent方法。

ViewGroup 想把自己分发给自己的onTouchEvent,需要拦截器onInterceptTouchEvent方法
return true 把事件拦截下来。

ViewGroup 的拦截器onInterceptTouchEvent 默认是不拦截的,所以return super.onInterceptTouchEvent()=return false;

View 没有拦截器,为了让View可以把事件分发给自己的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给自己的onTouchEvent。

关于事件分发机制里面拦截点击事件的方法
public class MyView extends LinearLayout{
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //返回true的话就是拦截事件不给这个布局下面的控件消费,返回false的话就是不给布局消费,直接传递给布局下面的控件消费
        //在哪个控件的坐标上就给哪个控件消费
        //这个方法是viewgroup独有的方法
        //事件分发机制三层 activity--》viewGroup--》view
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
}

继承的基类是ViewGroup 只有ViewGroup才有那个拦截点击事件的方法,因为布局也是继承ViewGroup的 所以也可以继承一些布局


还有解决滑动冲突的时候也是这么解决的,重写ViewPage 毕竟ViewPage也是继承ViewGroup的,所以我们可以根据当前手指滑动的距离来判断使用者需要进行哪个滑动

8.Android 加载大图时造成的内存问题

要想加载大图的时候不会造成OOM

BitmapFactory这个类提供了多个解析方法(decodeByteArray, decodeFile, decodeResource等)用于创建Bitmap对象,我们应该根据图片的来源选择合适的方法。比如SD卡中的图片可以使用decodeFile方法,网络上的图片可以使用decodeStream方法,资源文件中的图片可以使用decodeResource方法。


上面提到的方法都会自动的为我们的Bitmap对象分配内存,使用

BitmapFactory.Options options = new BitmapFactory.Options();

创建一个对象 再用options可以调用options.inJustDecodeBounds = true;就会禁止为我们的Bitmap分配内存了

BitmapFactory.decodeResource(getResources(), R.id.myimage, options);

这样options里面就会有图片的大小等数据了 再根据控件的大小 我们可以知道我们要加载的这个图片会不会比这个控件大,来确定加载的时候要不要压缩图片
如果图片比控件大很多,这时候我们就需要把图片压缩。

压缩的话有一个值需要注意 inSampleSize 这个是一个压缩比例 ,就是要比原来的比例变小几倍,这个数字可以通过原来的图片大小和控件大小的比例来算出

public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth(控件宽度), int reqHeight(控件高度)) {
        // 源图片的高度和宽度
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // 计算出实际宽高和目标宽高的比率
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
            // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

根据得出的inSampleSize

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
                                                         int reqWidth, int reqHeight) {
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
            final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        // 调用定义的方法计算inSampleSize值
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

我们就能得出一个Bitmap的图片对象我们再调用就设置好了图片

imgShowImg.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.drawable.test,100,100));

9.用getVisibility() 判断用户是否能看见并不好

getVisibility()只判断它自身是否是显示状态。但是如果它的父级不可见呢?
用 isShown() 方法更合适些,会先判断当前 View 的flag, 然后循环拿到父View,判断是不是可见。只要有一个是不可见的,就返回false。

10.Android自定义View(继承View)

构造方法
  1. 这个一般是在没有在布局文件里面声明组件的,都是在.java文件中new出来的对象使用的构造方法
    public ProgressCustom(Context context) {
        super(context);
    }
  1. 这个是布局文件有声明过的组件,在,java中findViewById后会使用的构造方法
    public ProgressCustom(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

这个构造方法可以在xml布局文件中写入自己想要的属性只要在res文件中创建一个attr的资源文件夹,里面可以创建一些你想要在自己控件内使用的属性


<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <declare-styleable name="Test">
        <attr name="test1" format="string" />
        <attr name="test2" format="integer" />
        <attr name="test3" format="reference" />
    </declare-styleable>
 
</resources>

其中attr标签就是我们自定义的属性了,name是属性名称,format是该属性可以取值的类型。
最后就可以在XML文件使用这些自定义属性,并且在代码中拿到了。当然,给属性取名字的时候最好不要跟一些控件的属性名字相同。

TypedArray array=context.obtainStyledAttributes(R.styleable.Test);
        String str = array.getColor(R.styleable.Test_test1, "123");
        array.recycle();

这样的话我们在上面得到了布局页面设置属性的值,这样就可以给我们的控件设置属性了。

onMeasure()

重写View里面的 onMeasure 方法的话,一般要对控件的模式进行判断,不然在我们设置控件为wrap_content的话会跟match_parent的效果一样

模式作用
MeasureSpec.AT_MOST这个是相当于布局文件里面的wrap_content
MeasureSpec.EXACTLY这个相当于布局文件里面的match_parent和一些固定的大小值
MeasureSpec.UNSPECIFIED要多大有多大(书上是这样写的)
onDraw()

重写里面的onDraw()方法,一般对象的初始化不要放在这个方法里面,因为在绘制UI的时候,这个方法会被调用很多次。

动态刷新自定义控件UI 可以调用postDelayed来刷新

getHandler().postDelayed(runnable, intervalTime(间隔时间));//间隔一段时间再进行重绘
private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            (你要干的事)
            invalidate();//重新绘制
        }
    };

动画

    /**
     * 透明
     */
    public void onclick1(View view){
        // alpha 参数(目标, 属性动画名, 参数...)
        ObjectAnimator aa = ObjectAnimator.ofFloat(view, "alpha", 0,1,0,1,0,1); // 透明度[0,1]
        aa.setDuration(2000);

        aa.start();
    }

    /**
     * 旋转
     */
    public void onclick2(View view){
        // rotation(旋转) / rotationX(X轴翻转) / rotationY(Y轴翻转)
        ObjectAnimator ra = ObjectAnimator.ofFloat(view, "rotationX", 0,180,180,360); // 角度
        ra.setDuration(2000);
        ra.start();
    }

    /**
     * 缩放
     */
    public void onclick3(View view){
        // scaleX(X轴缩放) / scaleY(Y轴缩放)
        ObjectAnimator sa = ObjectAnimator.ofFloat(view, "scaleX", 1,0,0,1); // 缩放比
        sa.setDuration(2000);
        sa.start();
    }

    /**
     * 位移
     */
    public void onclick4(View view){
        // translationX / translationY
        ObjectAnimator ta = ObjectAnimator.ofFloat(view, "translationX", 10,500,30,100); // 位移距离
        ta.setDuration(2000);
        ta.start();
    }

    /**
     * 组合动画
     */
    public void onclick5(View view){
        // 属性动画集
        AnimatorSet set = new AnimatorSet();

        ObjectAnimator aa = ObjectAnimator.ofFloat(view, "alpha", 0,1,0,1,0,1);
        ObjectAnimator ra = ObjectAnimator.ofFloat(view, "rotationX", 0,180,90,360);
        ObjectAnimator sa = ObjectAnimator.ofFloat(view, "scaleX", 0,1,0,1);
        ObjectAnimator ta = ObjectAnimator.ofFloat(view, "translationX", 10,500,30,100);

        set.setDuration(2000);

        // 添加到动画集
        // set.playSequentially(aa, ra, sa, ta); // 挨个执行
        set.playTogether(aa, ra, sa, ta); // 一起执行
        set.start();
    }

    /**
     * 两个属性动画组合(api>=21)
     */
    public void onclick6(View view){
        Path path = new Path();
        path.moveTo(0, 0); // 起始位置
        path.lineTo(100, 100); // 经过位置
        path.lineTo(50, 50);
        // (参数:目标, 属性动画名1, 属性动画名2, path) (两个属性名可以为不同类型)
        ObjectAnimator oa = ObjectAnimator.ofFloat(view, "rotationX", "rotationY", path);
        oa.setDuration(2000);
        oa.start();
    }

android studio 导入项目下载配置文件特慢的话

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        //jcenter()
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}       
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0'        
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
     //jcenter()
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

把jcenter()库注释掉 替换为阿里云的下载地址
image

接口回调的含义: 举例一个场景:

                    在自定义控件里面给控件设置单击事件,然后在自定义控件里面定义一个接口,接口里面有方法,在自定义控件的点击事件里面把接口方法填写进去,这样在activity里面调用的时候也能具体实现,还可以返回参数。

背景上半部分跟下半部分颜色不同 照成炫彩的效果 修改里面 endColor和startColor即可

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape android:shape="rectangle">
            <corners android:radius="@dimen/dp_5" />
            <gradient android:angle="-90" android:endColor="@color/background" android:startColor="@color/background" />
            <padding android:bottom="@dimen/dp_3" android:top="@dimen/dp_3" />
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <corners android:radius="@dimen/dp_5" />
            <solid android:color="@color/bg_shoukuan" />
            <padding android:bottom="@dimen/dp_3" android:top="@dimen/dp_3" />
        </shape>
    </item>
</selector>

android使用TabLayout设置标签之间背景间隔的时候可以设置直接在背景上下手脚

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">
        <!--<shape>
         <solid android:color="#ffffff"/>
         <corners android:topLeftRadius="10dp" android:topRightRadius="10dp" />
        </shape>-->
        <!--为了让TabLayout内部的Tab有间隔,暂时找不到其他设置方法,只能在背景图形里面设置间隔-->
        <layer-list>
            <item>
                <shape>
                    <solid android:color="@android:color/transparent"/>
                </shape>
            </item>
            <item android:left="@dimen/dp_50" android:right="@dimen/dp_50">
                <shape>
                    <corners android:topLeftRadius="@dimen/dp_30" android:topRightRadius="@dimen/dp_30" android:bottomLeftRadius="@dimen/dp_30" android:bottomRightRadius="@dimen/dp_30" />
                    <solid android:color="@color/white"/>
                </shape>
            </item>
        </layer-list>
    </item>
    <item android:state_selected="false">
        <!--<shape>
         <solid android:color="#bcbcbc"/>
         <corners android:topLeftRadius="10dp" android:topRightRadius="10dp" />
        </shape>-->
        <layer-list>
            <item>
                <shape>
                    <solid android:color="@android:color/transparent"/>
                </shape>
            </item>
            <item android:left="@dimen/dp_50" android:right="@dimen/dp_50">
                <shape>
                    <corners android:topLeftRadius="@dimen/dp_30" android:topRightRadius="@dimen/dp_30" android:bottomLeftRadius="@dimen/dp_30" android:bottomRightRadius="@dimen/dp_30" />
                    <solid android:color="@color/title_bg1"/>
                </shape>
            </item>
        </layer-list>
    </item>
</selector>

android 去除状态栏

// 隐藏状态栏 
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) 
// 显示状态栏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)

android 界面灰度化

地址

自定义一个布局文件,替换系统根布局
public class MyFramLayout extends FrameLayout {
    Paint mPaint = new Paint();

    public MyFramLayout(@NonNull Context context) {
        super(context);
    }

    public MyFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.setSaturation(0);
        mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.saveLayer(null,mPaint, Canvas.ALL_SAVE_FLAG);
        super.onDraw(canvas);

    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.saveLayer(null,mPaint, Canvas.ALL_SAVE_FLAG);
        super.dispatchDraw(canvas);

    }
}
@Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {

        if (("FrameLayout").equals(name)){
            int count = attrs.getAttributeCount();
            for (int i = 0; i < count; i++) {
                String Aname = attrs.getAttributeName(i);
                String Avalue = attrs.getAttributeValue(i);
                if (Aname.equals("id")){
                    int id = Integer.parseInt(Avalue.substring(1));
                    String idVal = getResources().getResourceName(id);
                    if ("android:id/content".equals(idVal)){
                        MyFramLayout framLayout = new MyFramLayout(context,attrs);
                        return framLayout;
                    }
                }
            }

        }
        return super.onCreateView(name, context, attrs);
    }

android Debug调试技巧

F7 程序执行下一行 不会进入官方方法 会进入自定义方法

F8 程序向下执行一行(如果当前行有方法调用,这个方法将被执行完毕返回,然后到下一行。就是说不会进入到调用的其他方法中去)

Shift+F8 进入了一个方法,觉得该方法没有问题,这个可以跳出当前方法

Alt+F9 设置多个断点 可以在多个断点之间跳来跳去

android 打包瘦身

1.开启混淆

 buildTypes {
        release {
            minifyEnabled true//true开启混淆配置,false关闭
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.duqian_android_keystore
        }
    }

2.只加载部分使用的SO库

ndk {
    abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a', 'arm64-v8a'
    }

更改打包apk名字

build.gradle文件头部添加:

def releaseTime() {
    return new Date().format("yyyyMMddHHmmss", TimeZone.getTimeZone("GMT+:08:00"))
}

build.gradle文件中buildTypes标签内添加:

        applicationVariants.all { variant ->
            variant.outputs.all {
                if (variant.name.endsWith("release")) {
                    outputFileName = "YFB-demo${releaseTime()}.apk"
                    //outputFileName = "AIJ.apk"
                }
            }
        }

设置沉浸式状态栏

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Window window = getWindow();
                WindowManager.LayoutParams attributes = window.getAttributes();
                attributes.flags |= flagTranslucentNavigation;
                window.setAttributes(attributes);
                getWindow().setStatusBarColor(Color.TRANSPARENT);
            } else {
                Window window = getWindow();
                WindowManager.LayoutParams attributes = window.getAttributes();
                attributes.flags |= flagTranslucentStatus | flagTranslucentNavigation;
                window.setAttributes(attributes);
            }
}

android设置按钮自定义背景设置好按钮长度后还有一层阴影

在按钮的xml属性上设置这个属性

style="?android:attr/borderlessButtonStyle"

android自定义setView 的Dialog设置圆角之类的背景失效

Window window = alertDialog.getWindow();
window.setBackgroundDrawableResource(android.R.color.transparent);

以及Dialog全屏显示

        Window window = alertDialog.getWindow();
        window.setBackgroundDrawableResource(android.R.color.transparent);
        window.setGravity(Gravity.BOTTOM);
        WindowManager.LayoutParams attributes = window.getAttributes();
        attributes.width = WindowManager.LayoutParams.MATCH_PARENT;
        attributes.height = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(attributes);

SmartRefreshLayout框架自定义刷新头动画

  1. 准备drawable动画
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item
        android:drawable="@drawable/ic_refresh_1"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_2"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_3"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_4"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_5"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_6"
        android:duration="100"/>
    <item
        android:drawable="@drawable/ic_refresh_7"
        android:duration="100"/>
</animation-list>
  1. 定义头部类
public class MyHeaderView extends LinearLayout implements RefreshHeader {
    private ImageView mProgressView;
    private AnimationDrawable mProgressDrawable;

    public MyHeaderView(Context context) {
        super(context);
        initView(context);
    }

    public MyHeaderView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.initView(context);
    }

    public MyHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.initView(context);
    }

    public MyHeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.initView(context);
    }

    private void initView(Context context) {
        setGravity(Gravity.CENTER);
        mProgressView = new ImageView(context);
        //设置动画
        mProgressView.setImageResource(R.drawable.shape_an_ref);
        mProgressDrawable = (AnimationDrawable) mProgressView.getDrawable();
        addView(mProgressView, SmartUtil.dp2px(50), SmartUtil.dp2px(50));
        setMinimumHeight(SmartUtil.dp2px(60));
    }

    @Override
    @NonNull
    public View getView() {
        return this;
    }

    @Override
    public SpinnerStyle getSpinnerStyle() {
        return SpinnerStyle.Translate;
    }

    @Override
    public void onStartAnimator(RefreshLayout layout, int headHeight, int maxDragHeight) {
        mProgressDrawable.start();//开始动画
    }

    @Override
    public int onFinish(RefreshLayout layout, boolean success) {
        mProgressDrawable.stop();//停止动画
        return 500;
    }

    @Override
    public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) {
        switch (newState) {
            case None:
            case PullDownToRefresh:
            case Refreshing:
                mProgressView.setVisibility(VISIBLE);
                break;
            case ReleaseToRefresh:
                break;
        }
    }

    @Override
    public boolean isSupportHorizontalDrag() {
        return false;
    }

    @Override
    public void onInitialized(RefreshKernel kernel, int height, int maxDragHeight) {
    }

    @Override
    public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {

    }

    @Override
    public void onReleased(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {

    }

    @Override
    public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) {
    }

    @Override
    public void setPrimaryColors(@ColorInt int... colors) {
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值