FloatingActionButton属性、用法,以及解析并解决sdk25以上只隐藏不显示的问题

2023-10-28

悬浮按钮(FloatingActionButton),在下文简称fab,今天我们来讲讲它的一些属性与用法,以及解析并解决sdk25以上FloatingActionButton只隐藏不显示的问题。

先展示一下动态图
这里写图片描述

本次开发环境基于sdk25.

使用之前要先引入design包

compile 'com.android.support:design:25.3.1'

xml属性

<android.support.design.widget.FloatingActionButton
        android:id="@+id/contact_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:layout_margin="10dp"
        android:src="@mipmap/ic_launcher"
        app:backgroundTint="@color/gray"
        app:backgroundTintMode="multiply"
        app:borderWidth="0dp"
        app:elevation="@dimen/activity_horizontal_margin"
        app:fabSize="auto"
        app:pressedTranslationZ="@dimen/activity_horizontal_margin"
        app:rippleColor="@color/gray"
        app:useCompatPadding="true" />
  • app:backgroundTint 按钮的背景颜色,不设置,默认使用theme中colorAccent的颜色
  • app:backgroundTintMode 按钮背景颜色的模式,在设置screen的时候就跟其他模式有点区别,区别在颜色变了,其他不变,具体不详,可忽略
  • app:borderWidth 该属性如果不设置0dp,那么在4.1的sdk上FAB会显示为正方形,而且在5.0以后的sdk没有阴影效果。所以设置为borderWidth=“0dp”
  • app:elevation 默认状态下阴影大小。
  • app:fabSize 设置大小,该属性有两个值,分别为normal和mini,对应的大小分别为56dp和40dp
  • app:pressedTranslationZ 按钮按下去的状态下的阴影大小
  • app:rippleColor 设置点击时的背景颜色
  • app:useCompatPadding 是否使用兼容的填充大小

用法

可与FloatingActionMenu或者CoordinatorLayout一起使用。在这里只拿CoordinatorLayout来做示例。

利用recyclerView的上下滑动来使fab显示或隐藏,点击fab显示snackbar

布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/contact_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

    </android.support.v7.widget.RecyclerView>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/contact_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:layout_margin="10dp"
        android:src="@mipmap/ic_launcher"
        app:backgroundTint="@color/turquoise"
        app:backgroundTintMode="src_in"
        app:borderWidth="0dp"
        app:elevation="5dp"
        app:fabSize="auto"
        app:pressedTranslationZ="50dp"
        app:rippleColor="@color/gray"
        app:useCompatPadding="true"
        app:layout_anchor="@+id/contact_recyclerview"
        app:layout_anchorGravity="bottom|right|end"
        app:layout_behavior="com.voctex.ui.tablayout.other.ScrollingViewBehavior" />


</android.support.design.widget.CoordinatorLayout>

代码实现

RecyclerView recyclerView= ((RecyclerView) findViewById(R.id.contact_recyclerview));

        recyclerView.setHasFixedSize(true);
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        //设置一个垂直方向的layout manager
        int orientation = LinearLayoutManager.VERTICAL;
        recyclerView.setLayoutManager(new LinearLayoutManager(mContext, orientation, false));

        List<String> mList=new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            mList.add("位置为:"+i);
        }

        TabLayoutAdapter tabLayoutAdapter=new TabLayoutAdapter(recyclerView,mList);

        recyclerView.setAdapter(tabLayoutAdapter);


        FloatingActionButton fab= ((FloatingActionButton) findViewById(R.id.contact_fab));
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v,"floatingActionBtn",Snackbar.LENGTH_SHORT)
                        .setAction("action", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                VtToast.s(mContext,"仙剑奇侠传");
                            }
                        }).show();
            }
        });

在以上代码中,只需要在xml中为fab指定一个属性就可以实现recyclerView在上下滑动时fab的显示或隐藏了。

app:layout_behavior="com.voctex.ui.tablayout.other.ScrollingViewBehavior"

而值就是自定义的一个类,继承于FloatingActionButton.Behavior,重写onStartNestedScroll和onNestedScroll这两个方法,相关代码如下:

package com.voctex.ui.tablayout.other;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by mac_xihao on 17/7/3.
 * (~ ̄▽ ̄)~ 嘛哩嘛哩哄
 */
public class ScrollingViewBehavior extends FloatingActionButton.Behavior {

    /**
     * 因为是在XML中使用app:layout_behavior定义静态的这种行为,
     * 必须实现一个构造函数使布局的效果能够正常工作。
     * 否则 Could not inflate Behavior subclass error messages.
     *
     * @param context
     * @param attrs
     */
    public ScrollingViewBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 处理垂直方向上的滚动事件
     *
     * @param coordinatorLayout
     * @param child
     * @param directTargetChild
     * @param target
     * @param nestedScrollAxes
     * @return
     */
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        // Ensure we react to vertical scrolling
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
                super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
                        nestedScrollAxes);
    }

    /**
     * 检查Y的位置,并决定按钮是否动画进入或退出
     *
     * @param coordinatorLayout
     * @param child
     * @param target
     * @param dxConsumed
     * @param dyConsumed
     * @param dxUnconsumed
     * @param dyUnconsumed
     */
    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
                dyUnconsumed);

        if (dyConsumed > 10 && child.getVisibility() == View.VISIBLE) {
            // User scrolled down and the FAB is currently visible -> hide the FAB
            //执行隐藏的动画
            child.hide();
        } else if (dyConsumed < -10 && child.getVisibility() != View.VISIBLE) {
            // User scrolled up and the FAB is currently not visible -> show the FAB
            //执行显示的动画
            child.show();
        }
    }
}

其实,到这里是应该结束的了,实现起来是很简单的,但是我在测试的时候却发现了一个比较坑的问题,就是RecylerView在滑动的时候,只能隐藏,却不显示fab。

解析并解决sdk25 FloatingActionButton只隐藏不显示的问题

这个问题坑呀,上网查看了不少人都是这么实现的,都是可以隐藏显示的,我就针对这个问题百度一下,发现有人在网上说sdk25以上的会出现不显示fab的问题,具体问题出现在了一下代码中:

sdk25以上,CoordinatorLayout的onNestedScroll方法会多出一段代码

 @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
            int dxUnconsumed, int dyUnconsumed) {
        final int childCount = getChildCount();
        boolean accepted = false;

        for (int i = 0; i < childCount; i++) {
            final View view = getChildAt(i);
            //sdk25以上会多出这个判断
            if (view.getVisibility() == GONE) {
                // If the child is GONE, skip...
                continue;
            }

            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            if (!lp.isNestedScrollAccepted()) {
                continue;
            }

            final Behavior viewBehavior = lp.getBehavior();
            if (viewBehavior != null) {
                viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed,
                        dxUnconsumed, dyUnconsumed);
                accepted = true;
            }
        }

        if (accepted) {
            onChildViewsChanged(EVENT_NESTED_SCROLL);
        }
    }

也就是CoordinatorLayout在滑动的时候,判断子view是否被设置为GONE,如果是,直接执行下一次循环,然后就不回调onNestedScroll,而我们自定义的那个类的onNestedScroll方法就不走了。

而在fab执行hide方法的时候,默认是把fab设置为GONE的,我们来看看fab中的hide方法

/**
     * Hides the button.
     * <p>This method will animate the button hide if the view has already been laid out.</p>
     */
    public void hide() {
        hide(null);
    }

    /**
     * Hides the button.
     * <p>This method will animate the button hide if the view has already been laid out.</p>
     *
     * @param listener the listener to notify when this view is hidden
     */
    public void hide(@Nullable OnVisibilityChangedListener listener) {
        hide(listener, true);
    }

    void hide(@Nullable OnVisibilityChangedListener listener, boolean fromUser) {
        getImpl().hide(wrapOnVisibilityChangedListener(listener), fromUser);
    }

最后是调用了以下代码,并且fromUser默认为true,这个值很关键

getImpl().hide(wrapOnVisibilityChangedListener(listener), fromUser);

接下来我们继续走下去,getImpl()是获得哪个对象

private FloatingActionButtonImpl getImpl() {
        if (mImpl == null) {
            mImpl = createImpl();
        }
        return mImpl;
    }

    private FloatingActionButtonImpl createImpl() {
        final int sdk = Build.VERSION.SDK_INT;
        if (sdk >= 21) {
            return new FloatingActionButtonLollipop(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        } else if (sdk >= 14) {
            return new FloatingActionButtonIcs(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        } else {
            return new FloatingActionButtonGingerbread(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        }
    }

在这里我们默认用4.0以上的手机进行测试,所以获得的对象是FloatingActionButtonIcs的实例,然后就进入看看它的hide方法是如何实现的。

@Override
    void hide(@Nullable final InternalVisibilityChangedListener listener, final boolean fromUser) {
        if (isOrWillBeHidden()) {
            // We either are or will soon be hidden, skip the call
            return;
        }

        mView.animate().cancel();

        if (shouldAnimateVisibilityChange()) {
            mAnimState = ANIM_STATE_HIDING;

            mView.animate()
                    .scaleX(0f)
                    .scaleY(0f)
                    .alpha(0f)
                    .setDuration(SHOW_HIDE_ANIM_DURATION)
                    .setInterpolator(AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR)
                    .setListener(new AnimatorListenerAdapter() {
                        private boolean mCancelled;

                        @Override
                        public void onAnimationStart(Animator animation) {
                            mView.internalSetVisibility(View.VISIBLE, fromUser);
                            mCancelled = false;
                        }

                        @Override
                        public void onAnimationCancel(Animator animation) {
                            mCancelled = true;
                        }

                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mAnimState = ANIM_STATE_NONE;

                            if (!mCancelled) {
                                mView.internalSetVisibility(fromUser ? View.GONE : View.INVISIBLE,
                                        fromUser);
                                if (listener != null) {
                                    listener.onHidden();
                                }
                            }
                        }
                    });
        } else {
            // If the view isn't laid out, or we're in the editor, don't run the animation
            mView.internalSetVisibility(fromUser ? View.GONE : View.INVISIBLE, fromUser);
            if (listener != null) {
                listener.onHidden();
            }
        }
    }

直接看onAnimationEnd方法里面,默认fromUser为true,所以在这里fab是直接被设置为了Gone,而CoordinatorLayout的onNestedScroll方法里的循环又判断子view为Gone的时候直接跳出执行下次循环,这里是很矛盾的。

那么在什么情况下fromUser为false呢?

因为hide(@Nullable OnVisibilityChangedListener listener, boolean fromUser)方法访问权限为default,只有同个包里面的类才能调用,我直接搜索了fab这个方法的调用,发现了还有两个方法调用了这个方法,分别是

private boolean updateFabVisibilityForAppBarLayout(CoordinatorLayout parent,
                AppBarLayout appBarLayout, FloatingActionButton child) {
            if (!shouldUpdateVisibility(appBarLayout, child)) {
                return false;
            }

            if (mTmpRect == null) {
                mTmpRect = new Rect();
            }

            // First, let's get the visible rect of the dependency
            final Rect rect = mTmpRect;
            ViewGroupUtils.getDescendantRect(parent, appBarLayout, rect);

            if (rect.bottom <= appBarLayout.getMinimumHeightForVisibleOverlappingContent()) {
                // If the anchor's bottom is below the seam, we'll animate our FAB out
                child.hide(mInternalAutoHideListener, false);
            } else {
                // Else, we'll animate our FAB back in
                child.show(mInternalAutoHideListener, false);
            }
            return true;
        }

        private boolean updateFabVisibilityForBottomSheet(View bottomSheet,
                FloatingActionButton child) {
            if (!shouldUpdateVisibility(bottomSheet, child)) {
                return false;
            }
            CoordinatorLayout.LayoutParams lp =
                    (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            if (bottomSheet.getTop() < child.getHeight() / 2 + lp.topMargin) {
                child.hide(mInternalAutoHideListener, false);
            } else {
                child.show(mInternalAutoHideListener, false);
            }
            return true;
        }

可以发现,这两个类里面,hide的方法都是传入false的,还有,从名字可以发现,这两个方法应该分别是针对appbarlayout和bottomSheet的,访问权限是私有的,所以可以继续在fab类里面搜索调用的地方,发现这两个方法,都在另外两个方法里面一起被调用了

@Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
                View dependency) {
            if (dependency instanceof AppBarLayout) {
                // If we're depending on an AppBarLayout we will show/hide it automatically
                // if the FAB is anchored to the AppBarLayout
                updateFabVisibilityForAppBarLayout(parent, (AppBarLayout) dependency, child);
            } else if (isBottomSheet(dependency)) {
                updateFabVisibilityForBottomSheet(dependency, child);
            }
            return false;
        }
@Override
        public boolean onLayoutChild(CoordinatorLayout parent, FloatingActionButton child,
                int layoutDirection) {
            // First, let's make sure that the visibility of the FAB is consistent
            final List<View> dependencies = parent.getDependencies(child);
            for (int i = 0, count = dependencies.size(); i < count; i++) {
                final View dependency = dependencies.get(i);
                if (dependency instanceof AppBarLayout) {
                    if (updateFabVisibilityForAppBarLayout(
                            parent, (AppBarLayout) dependency, child)) {
                        break;
                    }
                } else if (isBottomSheet(dependency)) {
                    if (updateFabVisibilityForBottomSheet(dependency, child)) {
                        break;
                    }
                }
            }
            // Now let the CoordinatorLayout lay out the FAB
            parent.onLayoutChild(child, layoutDirection);
            // Now offset it if needed
            offsetIfNeeded(parent, child);
            return true;
        }

也就是说,只有在(AppBarLayout或者BottomSheet)与fab同为兄弟布局的时候,然后在他们滑动的时候,fab才会正常显示和隐藏,那么其他布局怎么办?像RecyclerView这种情况下该怎么解决?

其实也很简单,只要不执行hide方法就行了,自己实现隐藏动画,我这里直接拿了fab隐藏的动画,进行了修改了一下,然后就变成了我自己的,接下来直接贴代码好了。

继承FloatingActionButton.Behavior,另外实现了一个类ScrollAwareFABBehavior,代码如下

package com.voctex.ui.tablayout.other;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by mac_xihao on 17/7/3.
 * (~ ̄▽ ̄)~ 嘛哩嘛哩哄
 */
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {


    /**
     * 因为是在XML中使用app:layout_behavior定义静态的这种行为,
     * 必须实现一个构造函数使布局的效果能够正常工作。
     * 否则 Could not inflate Behavior subclass error messages.
     *
     * @param context
     * @param attrs
     */
    public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
        super();
    }

    /**
     * 处理垂直方向上的滚动事件
     *
     * @param coordinatorLayout
     * @param child
     * @param directTargetChild
     * @param target
     * @param nestedScrollAxes
     * @return
     */
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
                                       FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {

        // Ensure we react to vertical scrolling
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL ||
                super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target,
                        nestedScrollAxes);
    }

    /**
     * 检查Y的位置,并决定按钮是否动画进入或退出
     *
     * @param coordinatorLayout
     * @param child
     * @param target
     * @param dxConsumed
     * @param dyConsumed
     * @param dxUnconsumed
     * @param dyUnconsumed
     */
    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
                               View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
                dyUnconsumed);

        if (dyConsumed > 10 && child.getVisibility() == View.VISIBLE) {
            // User scrolled down and the FAB is currently visible -> hide the FAB
            //执行隐藏的动画
            hide(child);
        } else if (dyConsumed < -10 && child.getVisibility() != View.VISIBLE) {
            // User scrolled up and the FAB is currently not visible -> show the FAB
            //执行显示的动画
            show(child);
        }

    }

    /**
     * 显示的动画
     */
    private void show(final View view) {
        view.animate().cancel();

        // If the view isn't visible currently, we'll animate it from a single pixel
        view.setAlpha(0f);
        view.setScaleY(0f);
        view.setScaleX(0f);

        view.animate()
                .scaleX(1f)
                .scaleY(1f)
                .alpha(1f)
                .setDuration(200)
                .setInterpolator(new LinearOutSlowInInterpolator())
                .setListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationStart(Animator animation) {
                        view.setVisibility(View.VISIBLE);
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {

                    }
                });
    }

    /**
     * 隐藏的动画
     */
    private void hide(final View view) {
        view.animate().cancel();
        view.animate()
                .scaleX(0f)
                .scaleY(0f)
                .alpha(0f)
                .setDuration(200)
                .setInterpolator(new FastOutLinearInInterpolator())
                .setListener(new AnimatorListenerAdapter() {
                    private boolean mCancelled;

                    @Override
                    public void onAnimationStart(Animator animation) {
                        view.setVisibility(View.VISIBLE);
                        mCancelled = false;
                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {
                        mCancelled = true;
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (!mCancelled) {
                            view.setVisibility(View.INVISIBLE);
                        }
                    }
                });
    }
}

然后在xml那里直接改成

app:layout_behavior="com.voctex.ui.tablayout.other.ScrollAwareFABBehavior"

发现看源码还是一件比较有趣的事,就是有点耗时间。

如果想仔细查看所有代码的话,可以直接导下我的项目自己运行,并测试。

项目地址:https://github.com/voctex/Kepler

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FloatingActionButton属性、用法,以及解析并解决sdk25以上只隐藏不显示的问题 的相关文章

随机推荐

  • PermissionX 1.7发布,全面支持Android 13运行时权限

    各位小伙伴们大家早上好 一年一度的PermissionX升级又来了 还记得上次发布PermissionX 1 6版本还是在去年10月份的时候 当时是对Android 12系统进行了支持 详情可以参考这篇文章 PermissionX 1 6发
  • 深度学习框架Pytorch傻瓜式安装教程

    前提 已经安装完minianaconda和pycharm minianaconda直接官网下载即可 minianaconda比起anaconda体量很小 pycharm专业版2020下载百度网盘链接 链接 https pan baidu c
  • 【Detectron2】入门02-使用自己的数据集

    Detectron2 official Documents https detectron2 readthedocs io tutorials datasets html 目录 COCO格式数据集 Standard dataset dict
  • Qt对象树

    对象树 Qt提供了对象树机制 能够自动 有效的组织和管理继承自QObject的Qt对象 每个继承自QObject类的对象通过它的对象链表 QObjectList 来管理子类对象 当用户创建一个子对象时 其对象链表相应更新子类对象信息 对象链
  • JVM优化

    java运行时数据区 程序计数器 线程私有 java虚拟机栈 线程私有 本地方法栈 线程私有 java堆 线程公用 方法区 线程公用 jvm内存分配 栈内存分配 私有的 不会存在线程安全 保存参数 局部变量 中间计算过程和其他的数据 退出方
  • redis复习

    1 关系型数据库和非关系型数据库 关系型数据库 Relational Database 和非关系型数据库 Non relational Database 或 NoSQL Database 之间的主要区别可以从以下几个方面进行理解 1 1 数
  • 机器学习(数据分析)数学基础——线性代数篇(五)线性方程组

    求解线性方程组也算是考研中的必备技能了 它往往出现在大题的第一问 注 本篇需要一些线性代数基础 1 首先我们来解决r n的情况 线性方程组 import numpy as np from scipy import linalg 定义A矩阵
  • [Codeforces] number theory (R1900) Part.2

    Codeforces number theory R1900 Part 2 题单 https codeforces com problemset page 1 tags number 20theory 1601 1900 294C Shaa
  • 欧拉角(Euler angles)

    前言 本人也就英语4级水平 由于本篇中存在大量学术词汇 翻译时必然会有不当之处 原文可以在下面的链接中找到 具体意义各位可以自行斟酌 标红的部分是已发现存疑的翻译 也请各位指正 维基百科 欧拉角 欧拉角 欧拉角是由Lenhard Euler
  • C# 序列化与反序列化

    在C 网络编程中 为了传输复杂的数据类型 如类类型和容器 例如Dictionary List 我们需要将其转换成字节数组 C 中提供了序列化和反序列化来实现该方式 先转换成内存流 在转换成 public static System IO M
  • C++ vector、string使用

    vector就是类似于一个数组的容器 内容比数组更加全面 很多操作都有自己的函数可以直接拿过来进行使用 主要函数就是 v push back k 尾插元素 v insert it k 在任意位置插入元素 v eraser it it k 删
  • 让Win32窗口程序拥有控制台窗口

    让Win32窗口程序拥有控制台窗口 首先 为什么我们有了普通窗口后还要控制台窗口呢 因为我们可以用它方便的输出调试信息 而且普通玩家看到了也会觉得很高端 如果他会输几条命令 可能他会以为自己就是黑客了 示例效果 WinMain作为入口函数后
  • Zotero

    利用zotero插件添加及修改参考文献样式 1 1 zotero插件安装 1 2 zotero插件功能介绍 1 2 1 Add Edit Citation 参考文献引用样式及插入方法 1 2 1 1 选择及添加参考文献样式 1 2 1 2
  • gettimeofday时间

    elpi Preferences Help Guide About Trac Wiki Timeline Roadmap Browse Source View Tickets Search Start Page Index History
  • pytorch训练网络时报错:RuntimeError: received 0 items of ancdata

    错误的原因 dataloader加载数据时 pytorch多线程共享tensor是通过打开文件的方式实现的 而打开文件的数量是有限制的 当需共享的tensor超过open files限制时 即会出现该错误 解决方案 1 修改多线程的tens
  • 用php写密码输入强度,php计算密码强度

    下面的php代码用于测试给定密码的强度 最高强度为100 param String string return float Returns a float between 0 and 100 The closer the number is
  • 一年半前端工作经验试水杭州:我是如何拿下网易、阿里和滴滴 offer 的

    由于微信外链限制 推荐阅读等链接无法点击 可点击阅读原文跳转至原文 查看外链 前言 笔者毕业于东北大学 大学毕业社招进入环球网 前端开发工程师一职 技术栈 React node Github 地址 成果 来到杭州的目标非常的明确 大厂 其实
  • 刷脸支付服务商正迎来一次新的革命

    对于对手机操作不熟练 特别是不方便拿手机的人而言 刷脸支付简直不能更方便 支付行业一直是红海市场 而随着智能刷脸支付的推广 支付被推向风口 支付行业正迎来一次新的革命 一方面 正是因为市场火热 支付行业的宏观监管日趋严格 新兴的人工智能技术
  • Android 中设置EditText输入框提示文本hint的字体大小

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 一 布局文件activity custom hint xml
  • FloatingActionButton属性、用法,以及解析并解决sdk25以上只隐藏不显示的问题

    悬浮按钮 FloatingActionButton 在下文简称fab 今天我们来讲讲它的一些属性与用法 以及解析并解决sdk25以上FloatingActionButton只隐藏不显示的问题 先展示一下动态图 本次开发环境基于sdk25 使