android自定义插值器

Interpolators are very useful to model movement for your UI elements. In this article, we’ll focus on how to create aesthetic motion by using two simple tools: animator and interpolator instances.

插值器对于UI元素的移动建模非常有用。 在本文中,我们将重点介绍如何通过使用两个简单的工具(动画器和插值器实例)来创建美学运动。

一些动画理论 (Some Animation Theory)

How do interpolators work? Well, when it comes to changing the property of an object over time, they take an initial and a final value and create a series of ‘middle values’ between them, according to a specific rule. This rule is a mathematical function. As an example, consider a simple geometric shape as an object of which properties can be animated. Let’s have a look at changing a property of this shape, namely, its horizontal position.

插补器如何工作? 好吧,当涉及到随时间改变对象的属性时,它们会根据一个特定的规则获取一个初始值和一个最终值,并在它们之间创建一系列“中间值”。 这个规则是数学函数 。 例如,将简单的几何形状视为可以对其属性进行动画处理的对象。 让我们看一下更改此形状的属性,即其水平位置。

线性变化 (Linear change)

The simplest interpolator is the linear interpolator. Give this interpolator an initial and final position, and the interpolator will calculate a series of middle points, equally separated from each other, along which the shape will pass in order to get to the final position. Take a look at how the square moves. From the graph of position over time, you can see that the position value follows a linear path through the graph as the position of the square changes. This illustrates that, per unit of time, the position value changes in equal parts, with no variation in speed. In other words, the linear interpolator creates constant speed.

最简单的内插器是线性内插器。 给此插值器一个初始位置和最终位置,插值器将计算一系列彼此相等的中间点,形状将沿着这些中间点经过以到达最终位置。 看一下正方形如何移动。 从位置随时间变化的图表中,您可以看到,随着正方形位置的变化,位置值遵循通过该曲线的线性路径。 这说明,每单位时间位置值均等变化,而速度没有变化。 换句话说,线性内插器产生恒定速度

缓和 (Easing)

Easing refers to a value’s speed changing over time. In the case of an object’s position, for example, you’ll see that its rate of motion changes, by moving slow and then fast or vice versa. Look at an example of the same shape as before, but now the shape changes its speed during its motion:

缓动是指值的速度随时间变化 。 例如,以对象的位置为例,您会看到它的运动速率发生了变化,先缓慢然后快速移动,反之亦然。 看一个与以前相同形状的示例,但是现在该形状会在其运动过程中改变其速度:

As you can see from the graph of the shape’s position over time, the value now plots a curved path. It illustrates quite clearly what’s happening:

从图形随时间变化的位置图中可以看到,该值现在绘制了一条弯曲路径。 它清楚地说明了正在发生的事情:

  • At first, as time passes, the value of position doesn’t change much; the shape has a slow movement.起初,随着时间的流逝,头寸的值变化不大; 形状移动缓慢。
  • As we reach the middle of our animation, the shape accelerates steeply. The shape now moves much faster because the change in position per unit of time is greater.当我们到达动画的中间时,形状急剧加速。 现在,形状移动得更快,因为每单位时间的位置变化更大。
  • Finally, it decelerates until it reaches zero speed; its motion finishes.最后,它减速直到达到零速度。 它的动作完成。

To create this kind of motion, we use easing interpolators, which create variable speed. This is the most appealing interpolator because of the characteristics it gives to objects that change. Usually, the kind of change that is more appealing to the eye is what is called an ease in-out, in which it accelerates at the start and decelerates at the end. It starts slow, becomes faster in the middle, and ends slow. Easing interpolators are perfect to animate objects in this way. So now, let’s look at how we can create them.

为了创建这种运动,我们使用缓动插值器 ,它们创建了可变速度 。 这是最吸引人的内插器,因为它为变化的对象赋予了特征。 通常,这种更吸引人的变化就是所谓的“ 缓入缓出” ,即从一开始就加速而在最后则减速。 它开始缓慢,中间变快,结束缓慢。 轻松的插值器非常适合以这种方式对对象进行动画处理。 现在,让我们看看如何创建它们。

贝塞尔曲线 (Bezier curves)

Bezier curves allow for graphical modeling of a numerical property changing over time, making them the de facto tool for creating the aesthetic motion we’ve talked about. The shape of an ease-in-out Bezier curve is modeled by four control points laid out in a graph of a certain value over time (the same kind as in our previous examples).

贝塞尔曲线允许对随时间变化的数值特性进行图形化建模,从而使它们成为创建我们已经讨论过的美学运动的实际工具。 缓入式贝塞尔曲线的形状由四个控制点建模,这些控制点以一定的值随时间变化(与我们之前的示例相同)。

The extreme points in this curve are fixed, and only the two middle points move. This is because the points in the extremes represent the start and end values, at the beginning and end of our animation’s time, respectively. Because of this, we only need two points in a graph to change the characteristics of the object’s movement. To modify this rate of acceleration and deceleration, the middle points, along with the fixed extreme points, create the path that is shown. This is done by De Casteljau’s algorithm, which provides a way of constructing Bezier curves using segments along control points.

该曲线中的极端点是固定的,只有两个中间点移动。 这是因为极端点分别代表动画时间的开始和结束时的开始和结束值。 因此,我们仅需要图形中的两个点即可更改对象运动的特征。 要修改加速和减速的速度,中间点以及固定的极限点将创建显示的路径。 这是由De Casteljau的算法完成的,该算法提供了一种使用沿控制点的线段构造贝塞尔曲线的方法。

Two fixed start and end points and two variable middle points make a motion-oriented Bezier curve
两个固定的起点和终点以及两个可变的中间点构成了运动定向的贝塞尔曲线

Check this site to see how the curves are constructed in an interactive way. If you’re into math, you’ll also see the parametric equation that represents De Casteljau’s algorithm for 2, 3, and 4 control points.

检查此站点以查看如何以交互方式构造曲线。 如果您正在学习数学,还将看到代表De Casteljau针对2、3和4个控制点的算法的参数方程式。

用于创建面向运动的贝塞尔曲线的工具 (A tool for creating motion-oriented Bezier curves)

The Android framework provides support for interpolating using Bezier curves. The middle control points mentioned before are precisely what the Android’s ease interpolation class (which we’ll cover in a bit) asks for when creating an instance. So all we need are these middle control points. Fortunately, there are some online tools that can help us customize Bezier curves in just the way we need them, and give us these points, which we then can use to create our custom interpolator. Check cubic-bezier.com and play with the parameters to creates Bezier curves like the one below. You can even preview how your animation will behave, so you can make sure it’s perfect.

Android框架支持使用Bezier曲线进行插值。 前面提到的中间控制点正是创建实例时Android的easy插值类(我们将稍作介绍)所要求的。 因此,我们需要的只是这些中间控制点。 幸运的是,有一些在线工具可以帮助我们按照需要的方式自定义贝塞尔曲线,并为我们提供这些点,然后我们就可以使用这些点来创建自定义插值器。 检查cubic-bezier.com并使用参数来创建类似于以下曲线的贝塞尔曲线。 您甚至可以预览动画的行为方式,因此可以确保它是完美的。

The Bezier curve customizer from cubic-bezier.com
来自cube-bezier.com的Bezier曲线定制器

在Android中创建和使用插值器 (Creating and using interpolators in Android)

For an Android case, let’s consider a CardView like the one below.

对于Android手机,让我们考虑以下CardView

This a custom view that we would like to expand and contract as a response to click events. Let’s explore how it would look like using a linear interpolator first, and then providing a custom ease interpolator that will help give it a more meaningful motion.

这是一个自定义视图,我们希望将其扩展和收缩以响应单击事件。 让我们先探索一下使用线性插值器,然后提供自定义缓和插值器的外观,该插值器将有助于使它更有意义。

使用ValueAnimator (Using ValueAnimator)

One simple approach for animating a View's properties is by using a ValueAnimator. It works by taking two values and creating values in between (so, an interpolation). By adding an AnimatorUpdateListener to it, you can perform an assignment of this animated value to your view's properties (or any other variable you want) in order to update them. Let's use them to update the width of our card, with the help of a flag that helps us determine if the card is being expanded or contracted.

一种动画化View属性的简单方法是使用ValueAnimator 。 它通过获取两个值并在两个值之间创建一个值(即插值)来工作。 通过向其中添加一个AnimatorUpdateListener ,您可以将此动画值分配给视图的属性(或所需的任何其他变量)以更新它们。 让我们使用它们来更新卡片的宽度,并借助一个标志来帮助我们确定卡片是否正在扩展或收缩。

setOnClickListener {       val widthAnimator =    ValueAnimator.ofInt(cardWidth, cardWidth + if (isExpanded) (-80).dp else 80.dp)        .apply {            addUpdateListener { animator ->                layoutParams.width = animator.animatedValue as Int            }        }}

Ok, now we have an animator that interpolates some values and we perform some assignments, that update the view with the animated value across time. We can tell the animator to start the animation.

好的,现在我们有了一个动画器,它可以内插一些值并执行一些分配,从而随着时间的推移以动画值更新视图。 我们可以告诉动画师开始动画。

widthAnimator.start()

For the height, we create a height animator, and create an AnimatorSet to play it together with the width animator. We also toggle our expanded/contracted flag when the animation's finished.

对于高度,我们创建一个高度动画师,并创建一个AnimatorSet来与宽度动画师一起播放。 动画完成后,我们还会切换扩展/收缩标志。

val heightAnimator =    ValueAnimator.ofInt(        cardHeight,        cardHeight + if (isExpanded) (-80).dp else 80.dp    )        .apply {            addUpdateListener { animator ->                layoutParams.height = animator.animatedValue as Int                // We can delete this call from the width animator,                // since this will do the layout update for both.                requestLayout()            }        }AnimatorSet().apply {    playTogether(widthAnimator, heightAnimator)    doOnEnd {        isExpanded = !isExpanded    }    start()}

We haven’t specified a duration, or the interpolator that we want to use, but ValueAnimator has a duration of 300 milliseconds and uses an AccelerateDecelerate interpolator as default values. We’ll get to that kind of interpolator shortly, but before that, we want to expand and contract the corners or our card.

我们没有指定持续时间或要使用的插值器,但是ValueAnimator的持续时间为300毫秒,并使用AccelerateDecelerate插值器作为默认值。 我们将很快使用这种插值器,但是在此之前,我们想扩大和缩小角落或卡片。

使用ObjectAnimator (Using ObjectAnimator)

There is a more specific implementation of ValueAnimator, named ObjectAnimator, which can be used to streamline the process of animating a property. This allows you to bypass the process of adding an AnimatorUpdateListener. We can use an instance of this to animate the card's corner radius.

还有一个ValueAnimator的更具体的实现,称为ObjectAnimator ,可以用来简化动画属性的过程。 这使您可以绕开添加AnimatorUpdateListener的过程。 我们可以使用此实例来制作卡的角半径动画。

val cornerAnimator = ObjectAnimator.ofFloat(    this,    "radius",    cornerRadius,    cornerRadius +            if (isExpanded) 6.dp.toFloat() else (-6).dp.toFloat())AnimatorSet().apply {    playTogether(widthAnimator, heightAnimator, cornerAnimator)    doOnEnd {        isExpanded = !isExpanded    }    start()}

Note that this only works with certain properties of which setters can be determined by the ObjectAnimator. For other cases, like the width and height, ValueAnimator is the adequate solution, since we can assign the changes manually via its update listener lambda.

请注意,这仅适用于某些属性,这些属性可以由ObjectAnimator确定。 对于宽度和高度等其他情况, ValueAnimator是合适的解决方案,因为我们可以通过其更新侦听器lambda手动分配更改。

LinearInterpolator类 (LinearInterpolator class)

Ok, now we can customize our animation with interpolators. Let’s start with the simpler one, the linear interpolator, and see what happens to our animation. We can assign an interpolator instance to an individual ValueAnimator or an AnimatorSet which will assign it to each of its animators. For this example, we'll assign a LinearInterpolator to our AnimatorSet. We can also change our duration to 500 ms to see more clearly what's happening.

好的,现在我们可以使用插值器自定义动画了。 让我们从简单的线性插值器开始,看看动画发生了什么。 我们可以将插值器实例分配给单个ValueAnimatorAnimatorSet ,然后将其分配给每个动画器。 在此示例中,我们将LinearInterpolator分配给AnimatorSet 。 我们还可以将持续时间更改为500毫秒,以更清楚地了解正在发生的情况。

AnimatorSet().apply {    interpolator = LinearInterpolator()    duration = 500    playTogether(widthAnimator, heightAnimator, cornerAnimator)    doOnEnd {        isExpanded = !isExpanded    }    start()}

The result is what we expect: a card expanding and contracting with linear speed, which doesn’t look that good.

结果就是我们所期望的:一张卡片以线性速度扩展和收缩,看起来并不好。

AccelerateDecelerateInterpolator类 (AccelerateDecelerateInterpolator class)

Now we enter into the easing interpolator territory. This class provides an easing interpolator with a set of hardwired values. As mentioned before, this is the default interpolator in ValueAnimator, so we don't need to assign it explicitly.

现在我们进入宽松插值器领域。 此类为缓动插值器提供了一组硬连线值。 如前所述,这是ValueAnimator的默认插值ValueAnimator ,因此我们无需显式分配它。

This already looks better, but we can improve on it further by making the easing effect a little more pronounced. Let’s make our own easing interpolator.

这看起来已经更好了,但是我们可以通过使缓和效果更加明显来进一步改进它。 让我们创建自己的缓动插值器。

PathInterpolator类 (PathInterpolator class)

Finally, let’s create our custom interpolator. Android’s class for a Bezier-defined ease interpolator is called PathInterpolator, and we can create one by passing the (x, y) coordinates of the two control points that model the curve.

最后,让我们创建我们的自定义插值器。 Android使用Bezier定义的缓和插值器的类称为PathInterpolator ,我们可以通过传递对曲线建模的两个控制点的(x,y)坐标来创建一个类。

val customInterpolator = PathInterpolator(x1, y1, x2, y2)

We can also define one via an XML file inside the anim resource directory:

我们还可以通过anim资源目录中的XML文件来定义一个:

<?xml version="1.0" encoding="utf-8"?><pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"    android:controlX1="0.8"    android:controlX2="0.35"    android:controlY1="0"    android:controlY2="1" />

And loading it like so:

像这样加载它:

val customInterpolator =     AnimationUtils.loadInterpolator(context, R.anim.ease)

Now it looks quite better. We can make further customizations to our view to make it look perfect. For example, making the text invisible during resizing, and making the duration customizable by providing a parameter that we can set from XML attributes. That way, we can have multiple card views that behave differently.

现在看起来好多了。 我们可以进一步定制视图以使其看起来完美。 例如,在调整大小时使文本不可见,并通过提供可以从XML属性设置的参数来使持续时间可自定义。 这样,我们可以拥有多个行为不同的卡片视图。

AnimatorSet().apply {    if (isAnimationFinished) {        playTogether(            widthAnimator,            heightAnimator,            cornerAnimator        )        interpolator = when (this@ResizableCardView.interpolator) {            LINEAR -> LinearInterpolator()            EASE -> AnimationUtils.loadInterpolator(                context,                R.anim.ease            )        }        duration = this@ResizableCardView.duration        doOnStart {            isAnimationFinished = false        }        doOnEnd {            cardDescription.startAnimation(fadeIn())            isExpanded = !isExpanded            isAnimationFinished = true        }        startCardAnimation()    }}

An extension for the AnimatorSet to handle the card’s body text fade:

AnimatorSet的扩展,用于处理卡的正文文本淡入淡出:

private fun AnimatorSet.startCardAnimation() {    // Custom fade animation with listener to wait for card's text    // body to finish fading before resizing.    val descriptionFadeOut = fadeOut().apply {        setListener {            onAnimationEnd {                // Our AnimatorSet start()                this@startCardAnimation.start()            }        }    }    cardDescription.startAnimation(descriptionFadeOut)}

Here’s our final custom view class.

这是我们的最终自定义视图类。

package mx.yellowme.youst.playground.ui.widgetsimport android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator
import androidx.core.animation.doOnEnd
import androidx.core.animation.doOnStart
import androidx.core.content.res.getResourceIdOrThrow
import com.google.android.material.card.MaterialCardView
import kotlinx.android.synthetic.main.resizable_card_view.view.cardDescription
import kotlinx.android.synthetic.main.resizable_card_view.view.cardTitle
import kotlinx.android.synthetic.main.resizable_card_view.view.header
import mx.yellowme.youst.core.extensions.consumeTypeArray
import mx.yellowme.youst.core.extensions.dp
import mx.yellowme.youst.core.extensions.fadeIn
import mx.yellowme.youst.core.extensions.fadeOut
import mx.yellowme.youst.core.extensions.inflate
import mx.yellowme.youst.core.hooks.animations.setListener
import mx.yellowme.youst.playground.R
import mx.yellowme.youst.playground.ui.widgets.ResizableCardView.Interpolator.EASE
import mx.yellowme.youst.playground.ui.widgets.ResizableCardView.Interpolator.LINEAR
import mx.yellowme.youst.playground.ui.widgets.ResizableCardView.Interpolator.values/*** Custom implementation of a [MaterialCardView] that expands and contracts with a click event.* The duration of the expansion animation, as well as the value interpolation, are customizable.* The interpolator can be either linear or ease.*/
class ResizableCardView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : MaterialCardView(context, attrs, defStyleAttr) {var duration: Long =DEFAULT_DURATION.toLong()lateinit var interpolator: Interpolatorvar cardBackground: Int = R.drawable.blue_gradientset(backgroundResource) {updateHeaderBackground(backgroundResource)}private var title: String = ""set(text) {field = textcardTitle.text = text}private var description: String = ""set(text) {field = textcardDescription.text = text}private var isAnimationFinished = trueprivate var isExpanded = falseinit {initCardView()setSizeChangeAnimation()attrs?.consumeTypeArray(context, R.styleable.ResizableCardView) {title = getString(R.styleable.ResizableCardView_resizableCardTitle) ?: ""description = getString(R.styleable.ResizableCardView_resizableCardDescription) ?: ""interpolator = values()[getInt(R.styleable.ResizableCardView_resizableCardInterpolator,LINEAR.ordinal)]duration =getInt(R.styleable.ResizableCardView_expandDuration, DEFAULT_DURATION).toLong()cardBackground =getResourceIdOrThrow(R.styleable.ResizableCardView_resizableCardBackground)}}private fun setSizeChangeAnimation() {setOnClickListener {val cardWidth = widthval cardHeight = heightval cornerRadius = radiusval widthAnimator =ValueAnimator.ofInt(cardWidth, cardWidth + if (isExpanded) (-80).dp else 80.dp).apply {addUpdateListener { animator ->layoutParams.width = animator.animatedValue as Int}}val heightAnimator =ValueAnimator.ofInt(cardHeight,cardHeight + if (isExpanded) (-80).dp else 80.dp).apply {addUpdateListener { animator ->// We can delete this call from the width animator,// since this will do the layout update for both.layoutParams.height = animator.animatedValue as IntrequestLayout()}}val cornerAnimator = ObjectAnimator.ofFloat(this,"radius",cornerRadius,cornerRadius +if (isExpanded) 6.dp.toFloat() else (-6).dp.toFloat())AnimatorSet().apply {playTogether(widthAnimator, heightAnimator)doOnEnd {isExpanded = !isExpanded}start()}AnimatorSet().apply {if (isAnimationFinished) {playTogether(widthAnimator,heightAnimator,cornerAnimator)interpolator = when (this@ResizableCardView.interpolator) {LINEAR -> LinearInterpolator()EASE -> AnimationUtils.loadInterpolator(context,R.anim.ease)}duration = this@ResizableCardView.durationdoOnStart {isAnimationFinished = false}doOnEnd {cardDescription.startAnimation(fadeIn())isExpanded = !isExpandedisAnimationFinished = true}startCardAnimation()}}}}private fun initCardView() {inflate(R.layout.resizable_card_view, context)cardElevation = 20.dp.toFloat()updateHeaderBackground(cardBackground)}private fun updateHeaderBackground(id: Int) {header.background = context.getDrawable(id)}private fun AnimatorSet.startCardAnimation() {// Custom fade animation with listener to wait for card's text// body to finish fading before resizing.val descriptionFadeOut = fadeOut().apply {setListener {onAnimationEnd {// Our AnimatorSet start()this@startCardAnimation.start()}}}cardDescription.startAnimation(descriptionFadeOut)}enum class Interpolator {LINEAR, EASE}companion object {const val DEFAULT_DURATION = 500}
}

结论 (Conclusion)

We’ve seen that we can create cool animations with nothing more than a pair of numbers consisting of initial and final values and letting an interpolator fill the middle points for us. Ease interpolators make such a difference in the way your views behave when compared to linear ones. And by using custom ease interpolators created withPathInterpolator, we can customize the way our animation changes speed with very little effort. Google provides documentation for its Material Design language, which contains guidelines that can help you follow good design practices in your app, and that includes good animation practices. If you want to know how to apply interpolators so that your app's UI is more expressive, then check out the Material Design documentation on motion principles.

我们已经看到,我们可以创建很酷的动画,只用一对由初始值和最终值组成的数字,并让插值器为我们填充中间点。 与线性视图相比, 缓和插值器在视图的行为方式上有很大不同。 通过使用由PathInterpolator创建的自定义缓动插值PathInterpolator ,我们可以以极少的努力自定义动画更改速度的方式。 Google提供了有关Material Design语言的文档,其中包含可以帮助您遵循应用程序中良好设计规范的准则,还包括良好的动画规范。 如果您想知道如何应用插值器以使您的应用程序的UI更具表现力,请查看有关运动原理的Material Design文档 。

翻译自: https://medium.com/yellowme/custom-ease-interpolator-for-meaningful-motion-in-android-4f6503398b89

android自定义插值器


http://www.taodudu.cc/news/show-2910965.html

相关文章:

  • Magnetic Levitation for Soft-Tethered Capsule Colonoscopy Actuated With a Single Permanent Magnet
  • 成像数据更好的展示_如何使用数据科学更好地了解您的客户
  • 简短加密_神经网络训练中回调的简短实用指南
  • 【DSA_Fall2020】2. Trees (Templates in C)
  • 使用2019.2 Terrain Tools更新来加速Terrain Material绘画
  • 数据驱动的营销方式和加拿大禁止Clearview AI
  • securecrt 不掉线_如何不掉线
  • 机器学习算法优缺点_用于机器学习的优化算法的优缺点
  • 【互联网人的英语】到底要不要学语法?什么时候学比较好?
  • 英语六级(词组、同义替换)
  • 英语--副词描述变化量大小
  • 企业级计算机储存容量,家用NAS与企业级NAS功能大比拼
  • 虚拟机可以做成存储服务器吗,利用win10自带虚拟机功能轻松打造家用nas
  • 家用NAS配置方案
  • 个人家用nas_家庭私有云盘系列教程-本地搭建家庭NAS方案
  • 树莓派家用NAS解决方案
  • 使用树莓派搭建家用 NAS
  • Ubuntu打造家用NAS二——服务器管理
  • 巴法络nas硬盘挂linux,教你轻松DIY——巴法络家用NAS使用详解
  • NAS实现家用服务器
  • 家用nas装linux和windows,你会用 NAS 给 PC 装系统吗?
  • win10 nas搭建_零起步自建家用NAS
  • 群晖家用NAS选购心得
  • 文件管理nas php,家用nas安装配置可道云进行文件管理
  • 家用NAS上安装Domino
  • 个人家用nas_方便易用的家用NAS私家云不超千元
  • diy nas配置推荐2019_Server2019+htpc+NAS搭建家庭数据中心+远程唤醒开关机+晒晒桌面...
  • 树莓派制作家用服务器,树莓派搭建家用小型NAS服务器
  • 个人家用nas_希捷个人云评测:家用NAS中的佼佼者
  • diy nas配置推荐2019_打造家用NAS之一(2019年版)

android自定义插值器_自定义缓动插值器,可在Android中实现有意义的动作相关推荐

  1. 自定义函数_自定义函数,让你的表格为所欲为

    自定义函数可以做什么?可以让你的表格为所欲为! 这篇文章教你如何掌握自定义函数. 函数是大家在使用 Excel 工作的过程中经常会用到的. 比如大家已经很熟悉了的求和函数 SUM,计数函数 COUNT ...

  2. android wifi 流程图_实现双wifi的方法及Android终端与流程

    本发明涉及无线通信技术领域,尤其涉及一种实现双wifi的方法及Android终端. 背景技术: 在楼宇对讲产品中,楼宇对讲的家庭设备,如平板,需要连接到楼宇对讲的局域网络,以实现与楼宇内的相关设备进行 ...

  3. flutter 自定义绘制_自定义可绘制

    flutter 自定义绘制 I love our new designs! Recently I've been working on user interactions. One of them i ...

  4. 怎么自定义字体_自定义字体@fontface的常见应用

    前言 @font-face允许网页自带字体,从而消除对用户电脑字体的依赖.基本用法如下: @font-face { font-family: "family-name"; /* 字 ...

  5. java自定义配置文件_自定义配置文件如何配置

    @Component public class RoleDirectiveModel implements TemplateDirectiveModel { /** * * @param enviro ...

  6. java自定义字段_自定义字段的设计与实现(Java实用版)

    前言 自定义字段又叫做"开放模型",用户可以根据自已的需求,添加需要的字段,实现个性化定制. 使用自定义字段的目的,使用自定义字段解决哪些问题 如现有一套CRM系统,客户模块中客户 ...

  7. python 列表自定义排序_自定义排序的Python列表

    我有一个dicts列表: ldicts = [{'name': '120-150'}, {'name': '90-120'}, {'name': '150-180'}, {'name': '>= ...

  8. zipkin 自定义采样率_分组,采样和批处理– Java 8中的自定义收集器

    zipkin 自定义采样率 在第一篇文章的后续部分,这一次我们将编写一些更有用的自定义收集器:用于按给定的标准进行分组,采样输入,批量处理以及在固定大小的窗口上滑动. 分组(计数事件,直方图) 假设您 ...

  9. 模板使用自定义类型_自定义虚幻图表_拓展蓝图功能

    最近研究了下虚幻的图表编辑器写法,制作了个基础模板给大家用来制作自己的编辑器~ 资源类型节点编辑器(提供了基础的节点编辑功能.并保存时转化为UObject的子类的运行时数据结构): Eragon-Br ...

最新文章

  1. linux 开机自启动设置 inittab 详解
  2. java之hibernate之 cascade和inverse
  3. 50题matplotlib从入门到精通
  4. 第二章 循环结构程序设计
  5. 算法面试:栈实现队列的方案
  6. 世界科学技术通史_全球科技通史
  7. Modeling and Analyzing the Influence of Chunk Size Variation on Bitrate Adaptation in DASH 名字解释0728
  8. Qt文档阅读笔记-Qt5录音功能的实现
  9. 支持pygame的python有哪些版本_完整构建文件支持PYGAME
  10. LSF-SCNN:一种基于 CNN 的短文本表达模型及相似度计算的全新优化模型
  11. heidisql导出为mysql_HeidiSQL工具导出导入MySQL数据
  12. *HDU1846HDU2188 巴什博奕
  13. 给datagrid模板页里面的控件动态赋值
  14. 伺服电机常用参数设置_伺服电机功能及作用_伺服电机参数设置
  15. 四种插头类型:XH、VH、SM、HY
  16. 自定义形状seekbar学习
  17. python画一棵树的心理测试_【心理测试】画树测试:一棵树读你的人生
  18. IO流_IO流小结图解
  19. 失物招领网站毕业设计,失物招领网站设计与实现,失物招领论文源码设计分析毕设作品参考
  20. (建议收藏)服务器宕机,效率排查攻略V2.0

热门文章

  1. BGP劫持原理及如何防御
  2. 基于改进二进制粒子群算法的配电网重构(matlab实现)
  3. 数据库为什么要分库分表
  4. 【荐书】C程序设计语言(第二版)
  5. 进击3D游戏界!Cocos Creator快速实现骨骼动画交互!
  6. MySQL练习题全部
  7. Warning: preg_match(): Compilation failed: PCRE does not support
  8. 小程序 身份认证服务器,如何实现微信小程序与.net core应用服务端的无状态身份验证...
  9. CAD偏移曲线(com接口c#语言)
  10. 删除数组中的重复项(保留最后一次出现的重复元素并保证数组的原有顺序)