Android强大的滚动控件RecyclerView

news2024/12/24 2:53:06

文章目录

  • Android强大的滚动控件RecyclerView
    • RecyclerView的基本用法
    • RecyclerView实现横向滚动
    • RecyclerView实现瀑布流布局
    • RecyclerView**的点击事件

Android强大的滚动控件RecyclerView

ListView由于其强大的功能,在过去的Android开发当中可以说是贡献卓越,直到今天仍然还有不计其数的程序在继续使用着ListView。不过ListView并不是完全没有缺点的,比如说如果我们不使用一些技巧来提升它的运行效率,那么ListView的性能就会非常差。还有,ListView的扩展性也不够好,它只能实现数据纵向滚动的效果,如果我们想实现横向滚动的话,ListView是做不到的。

为此,Android提供了一个更强大的滚动控件——RecyclerView。它可以说是一个增强版的ListView,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足之处。目前Android官方更加推荐使用RecyclerView,未来也会有更多的程序逐渐从ListView转向RecyclerView,那么本节我们就来详细讲解一下RecyclerView的用法。

首先新建一个RecyclerViewTest项目,并让Android Studio自动帮我们创建好活动。

RecyclerView的基本用法

和百分比布局类似,RecyclerView也属于新增的控件,为了让RecyclerView在所有Android版本上都能使用,Android团队采取了同样的方式,将RecyclerView定义在了support库当中。因此,想要使用RecyclerView这个控件,首先需要在项目的build.gradle中添加相应的依赖库才行。

打开app/build.gradle文件,在dependencies闭包中添加如下内容:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.recyclerview:recyclerview:1.2.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

添加完之后记得要点击一下Sync Now来进行同步。然后修改activity_main.xml中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

在布局中加入RecyclerView控件也是非常简单的,先为RecyclerView指定一个id,然后将宽度和高度都设置为match_parent,这样RecyclerView也就占满了整个布局的空间。需要注意的是,由于RecyclerView并不是内置在系统SDK当中的,所以需要把完整的包路径写出来。

这里我们想要使用RecyclerView来实现和ListView相同的效果,因此就需要准备一份同样的水果图片。简单起见,我们就直接从ListViewTest项目中把图片复制过来就可以了,另外顺便将Fruit类和fruit_item.xml也复制过来,省得将同样的代码再写一遍。

接下来需要为RecyclerView准备一个适配器,新建FruitAdapter类,让这个适配器继承自RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder。其中,ViewHolder是我们在FruitAdapter中定义的一个内部类,代码如下所示:

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view) {
super(view);
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
fruitName = (TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fruit_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}

虽然这段代码看上去好像有点长,但其实它比ListView的适配器要更容易理解。这里我们首先定义了一个内部类ViewHolder,ViewHolder要继承自RecyclerView.ViewHolder。然后ViewHolder的构造函数中要传入一个View参数,这个参数通常就是RecyclerView子项的最外层布局,那么我们就可以通过findViewById()方法来获取到布局中的ImageView和TextView的实例了。

接着往下看,FruitAdapter中也有一个构造函数,这个方法用于把要展示的数据源传进来,并赋值给一个全局变量mFruitList,我们后续的操作都将在这个数据源的基础上进行。

继续往下看,由于FruitAdapter是继承自RecyclerView.Adapter的,那么就必须重写onCreateViewHolder()、onBindViewHolder()和getItemCount()这3个方法。onCreateViewHolder()方法是用于创建ViewHolder实例的,我们在这个方法中将fruit_item布局加载进来,然后创建一个ViewHolder实例,并把加载出来的布局传入到构造函数当中,最后将ViewHolder的实例返回。onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行,这里我们通过position参数得到当前项的Fruit实例,然后再将数据设置到ViewHolder的ImageView和TextView当中即可。getItemCount()方法就非常简单了,它用于告诉RecyclerView一共有多少子项,直接返回数据源的长度就可以了。

适配器准备好了之后,我们就可以开始使用RecyclerView了,修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits(); //初始化水果数据
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits() {
for (int i = 0; i < 2; i++) {
Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
fruitList.add(orange);
Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
fruitList.add(pear);
Fruit grape = new Fruit("Grape", R.drawable.grape_pic);
fruitList.add(grape);
Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
fruitList.add(pineapple);
Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
fruitList.add(cherry);
Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
fruitList.add(mango);
}
}
}

可以看到,这里使用了一个同样的initFruits()方法,用于初始化所有的水果数据。接着在onCreate()方法中我们先获取到RecyclerView的实例,然后创建了一个LinearLayoutManager对象,并将它设置到RecyclerView当中。LayoutManager用于指定RecyclerView的布局方式,这里使用的LinearLayoutManager是线性布局的意思,可以实现和ListView类似的效果。接下来我们创建了FruitAdapter的实例,并将水果数据传入到FruitAdapter的构造函数中,最后调用RecyclerView的setAdapter()方法来完成适配器设置,这样RecyclerView和数据之间的关联就建立完成了。

现在可以运行一下程序了,效果如图所示:

在这里插入图片描述

可以看到,我们使用RecyclerView实现了和ListView几乎一模一样的效果,虽说在代码量方面并没有明显地减少,但是逻辑变得更加清晰了。当然这只是RecyclerView的基本用法而已,接下来我们就看一看RecyclerView还能实现哪些ListView实现不了的效果。

RecyclerView实现横向滚动

我们已经知道,ListView的扩展性并不好,它只能实现纵向滚动的效果,如果想进行横向滚动的话,ListView就做不到了。那么RecyclerView就能做得到吗?当然可以,不仅能做得到,还非常简单,那么接下来我们就尝试实现一下横向滚动的效果。

首先要对fruit_item布局进行修改,因为目前这个布局里面的元素是水平排列的,适用于纵向滚动的场景,而如果我们要实现横向滚动的话,应该把fruit_item里的元素改成垂直排列才比较合理。修改fruit_item.xml中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp" />
</LinearLayout>

可以看到,我们将LinearLayout改成垂直方向排列,并把宽度设为100dp。这里将宽度指定为固定值是因为每种水果的文字长度不一致,如果用wrap_content的话,RecyclerView的子项就会有长有短,非常不美观;而如果用match_parent的话,就会导致宽度过长,一个子项占满整个屏幕。

然后我们将ImageView和TextView都设置成了在布局中水平居中,并且使用layout_marginTop属性让文字和图片之间保持一些距离。

接下来修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
...
}

MainActivity中只加入了一行代码,调用LinearLayoutManager的setOrientation()方法来设置布局的排列方向,默认是纵向排列的,我们传入LinearLayoutManager.HORIZONTAL表示让布局横行排列,这样RecyclerView就可以横向滚动了。

重新运行一下程序,效果如图所示:

在这里插入图片描述

你可以用手指在水平方向上滑动来查看屏幕外的数据。

为什么ListView很难或者根本无法实现的效果在RecyclerView上这么轻松就能实现了呢?这主要得益于RecyclerView出色的设计。ListView的布局排列是由自身去管理的,而RecyclerView则将这个工作交给了LayoutManager,LayoutManager中制定了一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能定制出各种不同排列方式的布局了。

RecyclerView实现瀑布流布局

除了LinearLayoutManager之外,RecyclerView还给我们提供了GridLayoutManager和StaggeredGridLayoutManager这两种内置的布局排列方式。GridLayoutManager可以用于实现网格布局,StaggeredGridLayoutManager可以用于实现瀑布流布局。这里我们来实现一下效果更加炫酷的瀑布流布局,网格布局就作为课后习题,交给你自己来研究了。

首先还是来修改一下fruit_item.xml中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height=" wrap_content"
android:layout_margin="5dp" >
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginTop="10dp" />
</LinearLayout>

这里做了几处小的调整,首先将LinearLayout的宽度由100dp改成了match_parent,因为瀑布流布局的宽度应该是根据布局的列数来自动适配的,而不是一个固定值。另外我们使用了layout_margin属性来让子项之间互留一点间距,这样就不至于所有子项都紧贴在一些。还有就是将TextView的对齐属性改成了居左对齐,因为待会我们会将文字的长度变长,如果还是居中显示就会感觉怪怪的。

接着修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
StaggeredGridLayoutManager layoutManager = new
StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits() {
for (int i = 0; i < 2; i++) {
Fruit apple = new Fruit(
getRandomLengthName("Apple"), R.drawable.apple_pic);
fruitList.add(apple);
Fruit banana = new Fruit(
getRandomLengthName("Banana"), R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange = new Fruit(
getRandomLengthName("Orange"), R.drawable.orange_pic);
fruitList.add(orange);
Fruit watermelon = new Fruit(
getRandomLengthName("Watermelon"), R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruit pear = new Fruit(
getRandomLengthName("Pear"), R.drawable.pear_pic);
fruitList.add(pear);
Fruit grape = new Fruit(
getRandomLengthName("Grape"), R.drawable.grape_pic);
fruitList.add(grape);
Fruit pineapple = new Fruit(
getRandomLengthName("Pineapple"), R.drawable.pineapple_pic);
fruitList.add(pineapple);
Fruit strawberry = new Fruit(
getRandomLengthName("Strawberry"), R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruit cherry = new Fruit(
getRandomLengthName("Cherry"), R.drawable.cherry_pic);
fruitList.add(cherry);
Fruit mango = new Fruit(
getRandomLengthName("Mango"), R.drawable.mango_pic);
fruitList.add(mango);
}
}
private String getRandomLengthName(String name) {
Random random = new Random();
int length = random.nextInt(20) + 1;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; i++) {
builder.append(name);
}
return builder.toString();
}
}

首先,在onCreate()方法中,我们创建了一个StaggeredGridLayoutManager的实例。StaggeredGridLayoutManager的构造函数接收两个参数,第一个参数用于指定布局的列数,传入3表示会把布局分为3列;第二个参数用于指定布局的排列方向,传入StaggeredGridLayoutManager.VERTICAL表示会让布局纵向排列,最后再把创建好的实例设置到RecyclerView当中就可以了,就是这么简单!

没错,仅仅修改了一行代码,我们就已经成功实现瀑布流布局的效果了。不过由于瀑布流布局需要各个子项的高度不一致才能看出明显的效果,为此我又使用了一个小技巧。这里我们把眼光聚焦在getRandomLengthName()这个方法上,这个方法使用了Random对象来创造一个1到20之间的随机数,然后将参数中传入的字符串随机重复几遍。在initFruits()方法中,每个水果的名字都改成调用getRandomLengthName()这个方法来生成,这样就能保证各水果名字的长短差距都比较大,子项的高度也就各不相同了。

现在重新运行一下程序,效果如图所示:

在这里插入图片描述

当然由于水果名字的长度每次都是随机生成的,你运行时的效果肯定和图中还是不一样的。

RecyclerView**的点击事件

和ListView一样,RecyclerView也必须要能响应点击事件才可以,不然的话就没什么实际用途了。不过不同于ListView的是,RecyclerView并没有提供类似于setOnItemClickListener()这样的注册监听器方法,而是需要我们自己给子项具体的View去注册点击事件,相比于ListView来说,实现起来要复杂一些。

那么你可能就有疑问了,为什么RecyclerView在各方面的设计都要优于ListView,偏偏在点击事件上却没有处理得非常好呢?其实不是这样的,ListView在点击事件上的处理并不人性化,setOnItemClickListener()方法注册的是子项的点击事件,但如果我想点击的是子项里具体的某一个按钮呢?虽然ListView也是能做到的,但是实现起来就相对比较麻烦了。为此,

RecyclerView干脆直接摒弃了子项点击事件的监听器,所有的点击事件都由具体的View去注册,就再没有这个困扰了。

下面我们来具体学习一下如何在RecyclerView中注册点击事件,修改FruitAdapter中的代码,如下所示:

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruit> mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view) {
super(view);
fruitView = view;
fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
fruitName = (TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList) {
mFruitList = fruitList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.
fruit_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked view " + fruit.getName(),
Toast.LENGTH_SHORT).show();
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(), "you clicked image " + fruit.getName(),
Toast.LENGTH_SHORT).show();
}
});
return holder;
}
...
}

我们先是修改了ViewHolder,在ViewHolder中添加了fruitView变量来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件就可以了。这里分别为最外层布局和ImageView都注册了点击事件,RecyclerView的强大之处也在这里,它可以轻松实现子项中任意控件或布局的点击事件。我们在两个点击事件中先获取了用户点击的position,然后通过position拿到相应的Fruit实例,再使用Toast分别弹出两种不同的内容以示区别。

现在重新运行代码,并点击香蕉的图片部分,可以看到,这时触发了ImageView的点击事件。效果如图所示:

在这里插入图片描述

然后再点击菠萝的文字部分,由于TextView并没有注册点击事件,因此点击文字这个事件会被子项的最外层布局捕获到,效果如图所示:

在这里插入图片描述

如果对你有帮助,就一键三连呗(点赞+收藏+关注),我会持续更新更多干货~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055023.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言 | Leetcode C语言题解之第350题两个数组的交集II

题目&#xff1a; 题解&#xff1a; int cmp(const void* _a, const void* _b) {int *a _a, *b (int*)_b;return *a *b ? 0 : *a > *b ? 1 : -1; }int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size,int* returnSize) {qsort(nums1, nums1Size, s…

你还在手动刷公众号吗?‌试试 RSS 订阅,‌让信息自动汇聚

微信对于反爬的限制非常严格&#xff0c;之前有很多的方案&#xff0c;最后都是被封杀了。我这里列出一些我知道的、实践过的方案。 ‍ RSSHub 在路由“社交媒体”以及路由“新媒体”上都有很多方案&#xff0c;我基本都试过&#xff0c;但这些平台要么是收费的&#xff0c;…

图像数据处理17

四、形态学图像处理 4.3 开运算与闭运算 4.3.1开运算与闭运算的定义&#xff1a; 开运算&#xff1a;先腐蚀&#xff0c;再膨胀 闭运算&#xff1a;先膨胀&#xff0c;再腐蚀 记忆方法&#xff1a;膨胀&#xff08;胀开&#xff09;所以开运算最后对应的结果是膨胀&#x…

学习GitHub:注册与Linux环境对工作内容进行库分支上传

在这个数字化时代&#xff0c;GitHub已成为开发者们不可或缺的宝藏库。无论你是编程新手还是资深开发者&#xff0c;GitHub都能为你打开一扇通往无限创意与协作的大门。今天&#xff0c;就让我们一起踏上这段探索之旅&#xff0c;从GitHub的注册开始&#xff0c;再到如何在Linu…

blender内置树木的UV

之前听说用这个内置插件可以创建树木 我这边的默认配置出来的树木长这样&#xff0c;不得不想一下&#xff0c;他的uv怎么展&#xff0c;看起来好多树 我尝试看了一眼默认的UV 结果如下 好像每个树枝都已经是平铺的样子了&#xff0c;那么如果需要改的话&#xff0c;就根据…

SpringBoot 整合 Excel 轻松实现数据自由导入导出

01、背景介绍 在实际的业务系统开发过程中&#xff0c;操作 Excel 实现数据的导入导出基本上是个非常常见的需求。 之前&#xff0c;我们有介绍一款非常好用的工具&#xff1a;EasyPoi&#xff0c;有读者提出在数据量大的情况下&#xff0c;EasyPoi 会占用内存大&#xff0c;…

DMS:直接可微的网络搜索方法,最快仅需单卡10分钟 | ICML 2024

Differentiable Model Scaling&#xff08;DMS&#xff09;以直接、完全可微的方式对宽度和深度进行建模&#xff0c;是一种高效且多功能的模型缩放方法。与先前的NAS方法相比具有三个优点&#xff1a;1&#xff09;DMS在搜索方面效率高&#xff0c;易于使用。2&#xff09;DMS…

Javascript嵌套函数的调用

这里其实还是讲讲我对javascript闭包的认识。js中闭包就是以嵌套函数的外表出现的。内容是我自己琢磨的&#xff0c;我估计如果这个问题了解很清楚的话&#xff0c;javascript的闭包就没有问题了。其实这里探讨的是一个非常司空见惯&#xff0c;但是可能很多人没有注意的细节。…

SQL-函数篇

在SQL中&#xff0c;函数是用于执行特定操作的预定义代码块。它们可以帮助我们处理字符串、数值、日期等数据类型。下面是一些常用的SQL函数及其用法。 下面是一些常用的函数&#xff1a; 字符串函数 字符串函数用于操作和处理字符串数据。 -- 将两个字符串连接起来 select c…

爱心动画代码HTML5

这段代码是一个HTML5 Canvas动画&#xff0c;它通过JavaScript创建了一个动态的爱心效果。页面初始化时&#xff0c;首先定义了一些基本设置&#xff0c;如粒子数量、持续时间、速度等。然后&#xff0c;定义了Point和Particle类&#xff0c;用于处理粒子的位置和运动。接着&am…

部署Nginx负载均衡+动静分离的群集

目录 一、Nginx应用 二、正向代理与反向代理 1.1正向代理 1.2反向代理 三、负载均衡 1.轮询&#xff08;Round Robin&#xff09; 2.最小连接数 3.IP hash: 4.加权轮询 5.最少事件算法 6.一致性hash 一、Nginx应用 Nginx是一款非常优秀的HTTP服务器软件 支持高达50 …

【生日视频制作】洪崖洞高大楼AE模板修改文字软件生成器教程特效素材【AE模板】

洪崖洞企业高大楼生日视频制作教程AE模板改文字特效生成器素材 怎么如何做的【生日视频制作】洪崖洞企业高大楼AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

【JAVA八股文】持续更新中...

【-------------数据类型------------】 一、基本类型、包装类型 基本类型&#xff1a;整型&#xff08;byte short int long &#xff09;浮点型&#xff08;float double&#xff09;布尔型&#xff08;boolean&#xff09; 字符型&#xff…

【联想电脑】:使用拓展坞后转接HDMI,无法识别显示屏

项目场景&#xff1a; 作为一个嵌入式软件开发者&#xff0c;有两个外接屏幕&#xff0c;不足为奇。 但是在今天的使用电脑过程中&#xff0c;出现了接了一个拓展坞上面有HDMI接口&#xff0c;但是HDMI接口接上外接显示屏的时候电脑无法识别到&#xff0c;导致只有电脑直连的HD…

安装Pentaho Data Integration并启动

“pdi-ce-9.3.0.0-428.zip”包在 “/opt/software/”目录下。 步骤详情 1. 解压zip包2. 启动 Pentaho Data Integration PDI&#xff08;Kettle&#xff09; GUI 界面 1. 解压zip包 因为 Kettle 是绿色软件工具&#xff0c;开箱即用&#xff0c;无须安装。首先进入“/opt/soft…

ansible 中剧本的书写与运行

1.更改配置文件vim /etc/ansible/hosts 2.测试m0主机与s0、s1、s2&#xff0c;之间可以ping通 [rootm0 ansible]# ansible group02 -m ping 3.书写脚本文件 [rootm0 ~]# vim test0001.yml ​ --- - hosts: group02remote_user: roottasks: ​- name:…

【Qt】常用控件QLabel

常用控件QLabel QLabel可以用来显示文本和图片。 QLabel的属性 其核心属性如下&#xff1a; 属性说明 text QLabel 中的⽂本 textFormat ⽂本的格式. Qt::PlainText 纯⽂本Qt::RichText 富⽂本(⽀持 html 标签)Qt::MarkdownText markdown 格式Qt::AutoText 根据⽂本内容…

uniapp 页面跳转传参:父页面监听子页面传过来的数据

父页面 监听events事件 uni.navigateTo({url: "/components/watermark-camera",events: { // 重点重点重点重点重点重点重点重点getImages(data) { // 接收子页面抛出的 getImages 事件console.log("水印相机的照片&#xff1a;", data)}}})子页面 const …

人工智能和机器学习 3(复旦大学计算机科学与技术实践工作站)python机器学习、Pytorch库入门、d2l学习+<机器学习、神经网络————原理、理论>

前言 安装 — 动手学深度学习 2.0.0 documentation (d2l.ai)https://zh.d2l.ai/chapter_installation/index.html 安装 我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码&#xff0c;以快速入门并获得动手学习经验。 安装 Miniconda 最…

【css】水平对齐方式(justify、text-align、display: flex;)

一、justify 完整的属性名是 justify-contentjustify-content 用于定义位于同一行的项目在主轴&#xff08;通常是水平方向&#xff09;上的对齐方式。 center &#xff1a;居中start : 起始位置对齐&#xff08;左对齐&#xff09;end : 结束位置对齐&#xff08;右对齐&…