Android修行手册 - 使用ViewPager2实现画廊效果

news2024/11/24 9:09:54
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总
游戏脚本-辅助自动化Android控件全解手册再战Android系列
Scratch编程案例软考全系列Unity3D学习专栏
蓝桥系列ChatGPT和AIGC

👉关于作者

专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎底部卡片私我,交流让学习不再孤单

在这里插入图片描述

👉实践过程

最近想试试用ViewPager2来实现画廊的效果,ViewPager2和ViewPager在API上有的地方不同,ViewPager2是通过内部嵌套一个RecyclerView来实现的

😜效果

ViewPager2初始化的部分代码

private void initialize(Context context, AttributeSet attrs) {
        ...
        mRecyclerView = new RecyclerViewImpl(context);
        mRecyclerView.setId(ViewCompat.generateViewId());
        mRecyclerView.setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);

        mLayoutManager = new LinearLayoutManagerImpl(context);
        mRecyclerView.setLayoutManager(mLayoutManager);
        ...
        attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams());
}

这是实现之后的效果
在这里插入图片描述

实现画廊效果首先我们要考虑的是,如何让ViewPager2同时显示多个页面Item

clipChildren
我们知道,在Android中,布局中的控件超出父布局的大小部分不会被绘制,但是当clipChildren设置为false时,子View的内容可以超出父布局被绘制出来。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mLlRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/material_on_background_disabled"
    android:gravity="bottom"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/mLlFather"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="@color/black"
        android:gravity="bottom">

        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />
    </LinearLayout>
</LinearLayout>

当前没有设置根布局LinearLayout(mLlRoot) 的clipChildren属性,黑色部分为ImageView的父布局,clipChildren默认为true,界面的效果为:

可以看出,中间ImageView限制在了它的父布局中,此时我们修改clipChildren为false

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mLlRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/material_on_background_disabled"
    android:gravity="bottom"
    android:clipChildren="false"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/mLlFather"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="@color/black"
        android:gravity="bottom">

        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />
    </LinearLayout>
</LinearLayout>

界面效果为:


可以看出,ImageView超出了它的父布局绘制出了剩余的部分,由此如果一个ViewPager2要显示多个Item,我们可以这样,给ViewPager左边和右边设置一个margin、固定ViewPager大小,或者根据想要显示的Item个数动态计算ViewPager的大小,然后设置clipChildren=false,允许ViewPager中看不到的界面绘制出来。

😜思路

由此我将ViewPager2封装了一下,目的只是为了给ViewPager2套一层父布局,方便使用

class SuperViewPager : RelativeLayout {
 
     val mViewPager: ViewPager2 by lazy {
         findViewById<ViewPager2>(R.id.mViewPager)
     }
 
     //自己定义了一个比率,来调整画廊效果最左侧和最右侧占用的宽度
     var edgeRatio = 0.3
         set(value) {
             field = value
             refreshPageSize()
         }
 
     //为了保证画廊效果,可见的Page处理为单数
     var visibleItem: Int = 1
         set(value) {
             field = if (value.rem(2) == 0) {
                 value - 1
             } else {
                 value
             }
             refreshPageSize()
         }
 
 
     //刷新页面大小
     private fun refreshPageSize() {
         //使用post为了保证获取根布局width的时候结果不为0
         mViewPager.post {
             mViewPager.offscreenPageLimit = visibleItem
 
             //根据想要显示的页面个数,动态给ViewPager2计算一个大小
             val mPageWidth = if (visibleItem == 1) {
                 width
             } else {
                 width.toDouble().div(visibleItem.minus(2).plus(edgeRatio)).toInt()
             }
             mViewPager.layoutParams = LayoutParams(
                 LayoutParams(
                     mPageWidth,
                     ViewGroup.LayoutParams.MATCH_PARENT
                 ).apply { gravity = Gravity.CENTER })
         }
     }
     constructor(context: Context?) : super(context)
     constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
     constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
         context,
         attrs,
         defStyleAttr
     )
 
     init {
         clipChildren=false
         LayoutInflater.from(context).inflate(R.layout.super_viewpager_layout, this, true)
     }
 
     /**
      * 为ViewPager2设置一个适配器,ViewPager2的适配器不再是PagerAdapter,而是RecyclerView.Adapter类型
      */
     fun setAdapter(adapter: RecyclerView.Adapter<*>) {
         mViewPager.adapter = adapter
     }
 
     /**
      * 设置页面切换的效果
      */
     fun setPageTransformer(pageTransformer: ViewPager2.PageTransformer) {
         mViewPager.setPageTransformer(pageTransformer)
     }
 }

然后我们要为ViewPager2设置一个适配器,因为我这里是用Fragment作为单页内容来实现的多页面效果

class HomePagerAdapter(fragmentActivity: FragmentActivity) :
    FragmentStateAdapter(fragmentActivity) {
    override fun getItemCount(): Int {
        return 3
    }
    override fun createFragment(position: Int): Fragment {
        return SimpleFragment()
    }
}

关于ViewPager以及Adapter的正确使用方式,这里推荐看一下鸿神的一篇博客,讲的很详细:https://mp.weixin.qq.com/s/MOWdbI5IREjQP1Px-WJY1Q
最后在Activity中使用xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <com.utils.core.weight.viewpager.SuperViewPager
       android:id="@+id/mSuperViewPager"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="@color/black"
       android:clipChildren="true" />
</LinearLayout>

onCreate中调用

 mSuperViewPager.visibleItem = 3
 mSuperViewPager.setAdapter(HomePagerAdapter(this))

我们就得到了这样的效果:step1
在这里插入图片描述

其次,我们需要设置每个页面Item的间距,ViewPager2和ViewPager不同,ViewPager使用setPageMargin,但是因为ViewPager2内部是RecyclerView,有类似addItemDecoration的功能,我们添加自带的MarginPageTransformer

 mSuperViewPager.setPageTransformer(MarginPageTransformer(20))
 mSuperViewPager.visibleItem = 3
 mSuperViewPager.setAdapter(HomePagerAdapter(this))

就实现了这样的效果:step2
在这里插入图片描述

然后我们还要为ViewPager2添加一个画廊缩放的效果,ViewPager2的页面切换效果是通过PageTransformer实现的

public interface PageTransformer {

      /**
       * Apply a property transformation to the given page.
       *
       * @param page 当前页的View
       * @param 代表当前页面值和一个滑动距离的数值,在当前手机屏幕能看到的页面永远为0,往左递减,往右递增
       */
      void transformPage(@NonNull View page, float position);
  }

由此,我们实现PageTransformer,除去position=0(当前页面),其他页面设置一个默认效果,透明度0.5,缩放0.9,然后为页面由非0到0,以及0到非0设置一个过渡。

class GalleryTransformer : ViewPager2.PageTransformer {
    companion object {
        private const val TARGET_ALPHA = 0.5f
        private const val TARGET_SCALE = 0.8f
    }
    override fun transformPage(page: View, position: Float) {
        if (position < -1 || position > 1) {
            //当前页面左侧以及右侧的页面效果
            page.alpha = TARGET_ALPHA
            page.scaleX = TARGET_SCALE
            page.scaleY = TARGET_SCALE
        } else {
            //从不可见变为可见效果

            //透明度效果
            if (position <= 0) {
                page.alpha =
                    TARGET_ALPHA + TARGET_ALPHA * (1 + position)
            } else {
                page.alpha =
                    TARGET_ALPHA + TARGET_ALPHA * (1 - position)
            }
            //缩放效果
            val scale = Math.max(TARGET_SCALE, 1 - Math.abs(position))
            page.scaleX = scale
            page.scaleY = scale
        }
    }
}

最后在Activity设置PageTransformer,目前我们已经为ViewPager2设置过一个PageTransformer了,ViewPager2为我们提供了CompositePageTransformer,可以同时设置多个PageTransformer如下:

mSuperViewPager.setPageTransformer(CompositePageTransformer().apply {
    addTransformer(
        GalleryTransformer()
    )
    addTransformer(MarginPageTransformer(20))
})

最后就实现了如下效果:step3
在这里插入图片描述

目前我们看似完成了期望效果,但目前有小伙伴应该发现因为我们设置了ViewPager的宽度是没有填满根布局的,过渡滑动的效果很影响美感,我们第一反应肯定实在xml中加入android:overScrollMode=“never”

<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager2.widget.ViewPager2 xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mViewPager"
    android:clipChildren="false"
    android:layout_width="match_parent"
    android:overScrollMode="never"
    android:layout_height="match_parent">
</androidx.viewpager2.widget.ViewPager2>

再次运行效果如下:step4
在这里插入图片描述

并没有解决这个问题,因为ViewPager2内部并没有对overScrollMode进行处理,并且内部使用RecyclerView实现的,RecyclerView是ViewPager2的第一个子View,由此我们在SuperViewPager中加入

val mViewPager: ViewPager2 by lazy {
        findViewById<ViewPager2>(R.id.mViewPager).apply {
            //设置关闭过度滑动的效果
            getChildAt(0).overScrollMode = View.OVER_SCROLL_NEVER
        }
    }

再次运行,过渡滑动的效果就被去除了:step5
在这里插入图片描述
到这里,我们看似完成了一切的工作,但是目前有这样一个问题

经过多次试验,我用这种方式解决了这个问题,讲跟布局的Touch事件直接传递给ViewPager中的RecyclerView,在SuperViewPager中添加

override fun onTouchEvent(event: MotionEvent?): Boolean {
    return mViewPager.getChildAt(0).onTouchEvent(event)
}

到这,达到了我们期望的效果,下面是SuperViewPager完整代码

class SuperViewPager : RelativeLayout {

    val mViewPager: ViewPager2 by lazy {
        findViewById<ViewPager2>(R.id.mViewPager)
            .apply {
            //设置关闭过度滑动的效果
            getChildAt(0).overScrollMode = View.OVER_SCROLL_NEVER
        }
    }

    //自己定义了一个比率,来调整画廊效果最左侧和最右侧占用的宽度
    var edgeRatio = 0.3
        set(value) {
            field = value
            refreshPageSize()
        }

    //为了保证画廊效果,可见的Page处理为单数
    var visibleItem: Int = 1
        set(value) {
            field = if (value.rem(2) == 0) {
                value - 1
            } else {
                value
            }
            refreshPageSize()
        }


    //刷新页面大小
    private fun refreshPageSize() {
        //使用post为了保证获取根布局width的时候结果不为0
        mViewPager.post {
            mViewPager.offscreenPageLimit = visibleItem
            //根据想要显示的页面个数,动态给ViewPager2计算一个大小
            val mPageWidth = if (visibleItem == 1) {
                width
            } else {
                width.toDouble().div(visibleItem.minus(2).plus(edgeRatio)).toInt()
            }
            mViewPager.layoutParams = LayoutParams(
                LayoutParams(
                    mPageWidth,
                    ViewGroup.LayoutParams.MATCH_PARENT
                ).apply { gravity = Gravity.CENTER })
        }
    }

    /**
     * 将根布局的触摸事件直接传递给ViewPager
     */
    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        return mViewPager.getChildAt(0).onTouchEvent(event)
    }

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    init {
        clipChildren=false
        LayoutInflater.from(context).inflate(R.layout.super_viewpager_layout, this, true)
    }

    /**
     * 为ViewPager2设置一个适配器,ViewPager2的适配器不再是PagerAdapter,而是RecyclerView.Adapter类型
     */
    fun setAdapter(adapter: RecyclerView.Adapter<*>) {
        mViewPager.adapter = adapter
    }

    /**
     * 设置页面切换的效果
     */
    fun setPageTransformer(pageTransformer: ViewPager2.PageTransformer) {
        mViewPager.setPageTransformer(pageTransformer)
    }
}

调用时

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
  
      <com.utils.core.weight.viewpager.SuperViewPager
          android:id="@+id/mSuperViewPager"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@color/black" />
  </LinearLayout>
mSuperViewPager.setPageTransformer(CompositePageTransformer().apply {
    addTransformer(
        GalleryTransformer()
    )
    addTransformer(MarginPageTransformer(20))
})
mSuperViewPager.visibleItem = 3
mSuperViewPager.setAdapter(HomePagerAdapter(this))

😜遗留的问题

  • 有心的小伙伴可以发现,step1中,ViewPager2多页面的情况下,页面切换时,边缘的页面会出现闪动,目前还没发现什么原因。

  • 在SuperViewPager的layout布局中,我为ViewPager2设置了android:clipChildren=“false”,然后在初始化SuperViewPager,我为根布局也设置了clipChildren=false, 我搜了下资料,因为ViewPager2 设置android:clipChildren="false"是为了使得内部的View突破限制显示,根布局再设置一次是为了承载页面的ViewPager2 能突破限制,所以要设置两次,但目前我在上面讲clipChildren的时候,根LinearLayout嵌套了一个子LinearLayout,在子LinearLayout中添加的ImageView,我只在根LinearLayout设置了android:clipChildren=“false”,就实现了我想要的效果,不知道这里是为何,是因为ViewPager2 内部是RecyclerView吗?

  • 在处理多页面边缘手势事件时,我一开始使用的方法是

override fun onTouchEvent(event: MotionEvent?): Boolean {
   return mViewPager.dispatchTouchEvent(event)
}

将事件分发给内部的ViewPager,但是出现一个问题

我又仔细看了一次View,ViewGroup的事件分发机制的,但是按理说左边已经响应的话,右边也应该响应,由于Android 11 的API ViewGroup这块 dispatchTouchEvent内容有点多,打断点由于使用的API和手机版本不同也没找到原因。有没有小伙伴清楚这个问题出现的原因能够分享一下

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

温馨提示点击下方卡片获取更多意想不到的资源。
空名先生

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

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

相关文章

青少年CTF之PHP特性练习(1-5)

青少年CTF-PHP特性练习 文章目录 青少年CTF-PHP特性练习PHP特性01PHP特性02PHP特性03PHP特性04PHP特性05 PHP特性01 看给出的源码&#xff0c;两个变量的值加密后的MD5相同 <?php$s1 "%af%13%76%70%82%a0%a6%58%cb%3e%23%38%c4%c6%db%8b%60%2c%bb%90%68%a0%2d%e9%47…

使用Arthas排查性能问题

Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#xff0c;类加载信…

小程序----使用图表显示数据--canvas

需求&#xff1a;在小程序上实现数据可视化 思路&#xff1a;本来想用的是echarts或者相关的可视化插件&#xff0c;但因为用的是vue3&#xff0c;大多数插件不支持&#xff0c;所以用了echarts&#xff0c;但最后打包的时候说包太大超过2M无法上传&#xff0c;百度了一下&…

汽车功能安全ISO26262

一、功能安全基本概念及功能安全管理 什么是功能安全 相关标准&#xff1a; 现状&#xff1a; 功能安全的目的和范围&#xff1a; 总体框架&#xff1a; 基本定义&#xff1a;

vue3中toRaw 与 markRaw

toRaw 返回由 reactive 或 readonly 方法转换成响应式代理的普通对象。 这是一个还原方法&#xff0c;可用于临时读取&#xff0c;访问不会被代理/跟踪&#xff0c;写入时也不会触发界面更新。 markRaw 标记一个对象&#xff0c;使其永远不会转换为代理。返回对象本身 应…

企业软件手机app定制开发新趋势|网站小程序搭建

企业软件手机app定制开发新趋势|网站小程序搭建 随着移动互联网的快速发展和企业数字化转型的加速&#xff0c;企业软件手机App定制开发正成为一个新的趋势。这种趋势主要是由于企业对于手机App的需求增长以及现有的通用应用不能满足企业特定需求的情况下而产生的。 首先&#…

解决:AttributeError: module ‘os’ has no attribute ‘mknod’

解决&#xff1a;AttributeError: module ‘os’ has no attribute ‘mknod’ 文章目录 解决&#xff1a;AttributeError: module os has no attribute mknod背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时&#xff0c;报错…

小航助学题库蓝桥杯题库stem选拔赛(21年3月)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSD…

小航助学题库蓝桥杯题库stem选拔赛(22年1月)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSD…

【JDK21】详解虚拟线程

目录 1.概述 2.虚拟线程是为了解决哪些问题 2.1.线程切换的巨大代价 2.2.哪些情况会造成线程的切换 2.3.线程资源是有限的 3.虚拟线程 4.适用场景 1.概述 你发任你发&#xff0c;我用JAVA8&#xff1f;JDK21可能要对这句话say no了。 现在Oracle JDK是每4个版本&#x…

Android系统源码中添加可编译运行执行程序,C,C++

文章目录 Android系统源码中添加可编译运行执行程序&#xff0c;C&#xff0c;C1. 源码product分区中添加可执行程序 Android系统源码中添加可编译运行执行程序&#xff0c;C&#xff0c;C 1. 源码product分区中添加可执行程序 新建一个文件夹&#xff0c;以及一个test.cpp文…

【设计模式】03:单例模式

单例模式 OVERVIOW 单例模式1.单例模式实现2.饿汉与懒汉&#xff08;1&#xff09;饿汉模式&#xff08;2&#xff09;懒汉模式 3.懒汉线程安全1&#xff08;1&#xff09;引入互斥锁&#xff08;2&#xff09;引入双重检查锁定&#xff08;3&#xff09;引入原子变量 4.懒汉线…

RWA+AI 叙事下的 ProsperEx,对 Web3 时代交易的重新定义

RWA&#xff08;Real World Assets&#xff09;即现实资产代币&#xff0c;其本质在于将现实世界中具有货币价值的东西转化为数字代币&#xff0c;使其可以在区块链上表现价值并进行交易。RWA 资产既可以包括有形资产&#xff0c;例如房产、珠宝、黄金等&#xff0c;也可以包无…

第一节HarmonyOS DevEcoStudio工具下载以及环境搭建

一、下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 进入DevEco Studio 工具下载官网&#xff1a;https://developer.harmonyos.com/cn/develop/deveco-stu…

OpenCvSharp从入门到实践-(04)色彩空间

目录 1、GRAY色彩空间 2、从BGR色彩空间转换到GRAY色彩空间 2.1色彩空间转换码 2.2实例 BGR色彩空间转换到GRAY色彩空间 3、HSV色彩空间 4、从BGR色彩空间转换到HSV色彩空间 4.1色彩空间转换码 4.2实例 BGR色彩空间转换到HSV色彩空间 1、GRAY色彩空间 GRAY色彩空间通常…

上游任务和下游任务

起源多任务学习中的定义理解结合定义分析例子示例 1&#xff1a;计算机视觉示例 2&#xff1a;自然语言处理示例 3&#xff1a;语音处理示例 4&#xff1a;强化学习总结 起源 "上游任务"和"下游任务"这两个术语在深度学习领域中通常用来描述一种 多任务学…

适用于iOS 的顶级苹果数据恢复软件

数据丢失可能随时发生在任何人身上&#xff0c;这可能是一种令人沮丧的经历。丢失 iOS 设备上的重要数据可能会造成特别严重的损失&#xff0c;因为其中可能包括有价值的照片、联系人、消息和其他重要文件。幸运的是&#xff0c;有多种数据恢复工具可以帮助用户恢复丢失的数据。…

Java数据结构与算法----字符串匹配(KMP算法)

KMP算法简介 是一种线性时间复杂度的字符串匹配、查找算法。 暴力实现字符串匹配 对于字符串的匹配&#xff0c;可以使用暴力进行匹配&#xff1a; 如图进行演示:&#xff08;以a串 ABABABCAA 被b串 ABABC 匹配为例&#xff09;&#xff1a; 第一轮匹配&#xff1a;&#x…

Linux静态库,共享库,计算机基础知识

1.库文件: 1).库文件库是一组预先编译好的方法的集合;Linux系统存储库的位置一般在/lib 和 /usr/lib (64位系统/usr/lib64)库的头文件放在/usr/include 2).库的分类 静态库:libxxx.a(命名规则) 共享库:libxxx.so(命名规则) 3).准备文件: //add.c int add(int x,int y) { retu…

前端学习系列之html

目录 初识html 发展史 优势 W3C 标准 地址 格式 网页基本标签 标题标签 段落标签 换行标签 水平线标签 字体样式 注释和特殊符号 特殊符号 图像、超链接 图像 常见图像格式 格式 超链接 格式 重要属性 href&#xff1a;规定链接指向的页面的 URL target…