2023百度移动端lec2-lec4

2023百度移动端lec2-lec4

SYuan03 Lv4

Day 7.11-第二讲

大作业UI示意稿:见Gitee平台-UI_Resources
7.11-7.13课程中的Demo工程:见Gitee平台-UI Lesson Demo

运行环境搭建

AndroidStudio

Kotlin语言简介

文件结构介绍

运行

跟平板练了下

跑了整整6m40s额

日志logcat

退到后台显示onPause

再回去就onResume

现在的过滤器方式已经改变了

参考Android Studio2022年10月更新Logcat配置过滤_android studio logcat 过滤_baoolong的博客-CSDN博客

可以这样写,与老师上课所讲基本相当

APK包组成

两个资源文件一个是运行时参与编译,一个就是单纯的素材存储

渠道信息:比如小米应用商店,谷歌商店等信息

APK包构建过程

Design&&Code

一般不直接使用Design的方式

拖拽的方式不太精准

Day 7.12-第三讲-UI开发初探

图标: https://icons8.com/icons/material
主题:https://m3.material.io/theme-builder#/custom

View组件

View的属性

ViewGroup

例子

常见的布局

RelativeLayout相对用的比较少了

LinearLayout

LinearLayout例子

关于weight和layout_width和layout_height:理解是如果使用weight来分配,最好把对应的就设为0dp,如果不设置为0,可能是按比例分配后再增加

当然也可以抛弃weight,直接就单纯使用数值dp为单位

可以让内部的TextView居中

FrameLayout

左上角为原点,堆叠

堆叠顺序

wrap_content

  1. android:layout_width:这个属性指定了视图的宽度。它可以采用不同的值,包括:
    • "wrap_content":视图的宽度将根据其内容自适应。换句话说,视图的宽度将根据其内容的尺寸来确定。
  2. android:layout_height:这个属性指定了视图的高度。它可以采用不同的值,包括:
    • "wrap_content":视图的高度将根据其内容自适应。换句话说,视图的高度将根据其内容的尺寸来确定。

FrameLayout

  • bias: 偏差,对相对位置进行调整,通常设置0到1之间的值,可以改变组件在水平或垂直方向上的偏移。如,水平偏差设置为0时候,组件靠近左侧约束,而设置为1时,组件靠近右侧约束

  • chains: 链,链的作用是在水平或垂直方向上分配组件的控件。可以设置链的样式,“spread”(均匀分布空间)、“spread_inside”(在组件内部均匀分布空间)、和"packed"(将组件紧密相连)

    spreadspread_inside 的区别,以三个控件举例,spread 的第二个控件在中间,第一个和第三个则分别分布在左右剩余区域的中间位置,而spread_inside 的第二个控件在中间,第一个和第三个控件则分别紧贴父容器的左右两侧

  • dimension ratio: 尺寸比例,设置组件的宽度与高度之间的比例

bias

相对位置进行调整

为什么要用四个parent?,不直接center?

感觉是这种布局没gravity的概念,也许只能在linearlayout或者framelayout用,而且bias也用不了,只能像上面注释掉的这么用

chains

“spread”(均匀分布空间)、“spread_inside”(在组件内部均匀分布空间)、和"packed"(将组件紧密相连)

DimensionRatio

指定height或者width,另一个指定为0,通过ration确定另一个

常用控件

常用控件:

控件名称 描述
TextView 文本显示控件
Button 按钮控件
EditText 文本编辑框控件
ImageView 图片显示控件
ImageButton 图片作为按钮的控件
RadioGroup 单选按钮控件
CheckBox 复选框控件
Spiner 下拉列表控件
SeekBar 拖动条控件
ProgressBar 进度条控件
ScrollView 可滚动视图控件
DatePicker 日期显示控件
TimePicker 事件显示控件
Dialog 对话框控件
Toast 信息提示框控件

属性需要的时候在网上搜就好了

Context

简单了解

布局管理器

实践

先连接箭头对齐(或者说贴紧)

再调整右侧属性控制偏移量

方法一:设置onClick属性

有报红,但能跑。

方法二:使用代码的方法

见代码LessonThreeActivity

随堂练习

Day 7.13-第四讲-UI开发详解

动画模拟的网站http://inloop.github.io/interpolator/

TextView

简单介绍

常用属性

省略方式: ...出现的位置可控

基本用不到

Spannable:处理文本样式

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SpannableString span = new Spannablestring("红色打电话斜体删除线绿色下划线图片:.");
//1.设置背景色,setspan时需要指定的flag,Spanned .SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)
span.setspan(new Foregroundcolorspan(Color.RED), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//2.用超链接标记文本
span.setSpan (new URLSpan("tel: 4155551212"), 2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//3.用样式标记文本(斜体)
span.setSpan (new StyleSpan(Typeface.BOLD_ITALIC), 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//4.用删除线标记文本
span.setSpan (new StrikethroughSpan(), 7, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//5. 用下划线标记文本
span.setSpan (new UnderlineSpan(), 10, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ;
//6. 用颜色标记
span.setSpan (new ForegroundColorSpan(Color. GREEN), 10, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//7.1/获取Drawable资源
Drawable d = getResources().getDrawable(R.drawable.icon);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight ());
//8.创建Imagespan,然后用Imagespan来替换文本
ImageSpan imgspan = new ImageSpan(d, ImageSpan. ALIGN_BASELINE);
span.setSpan(imgspan, 18, 19, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
ti.setText(span);

RecycleView:可滑动的列表UI组件

基本组成

  • Data:数据,需要展示的内容

  • RecycleView:一个可滑动的列表View

  • Layout:XML文件

    布局(Layout):布局是指定义RecyclerView中每个项目的外观和结构的XML文件。它定义了表示列表中单个项目的视图的布局。

  • Layout manager:负责处理View 的UI组件

    • 每个ViewGroup 都有一个LayoutManager
    • 用于排列展示RecycleView 中的每一个item
    • 回收/复用 离开屏幕对于用户不可见的item
    • 内置的布局管理器:
      • LinearLayoutManager(线性)
      • GridLayoutManager(网格)
      • StaggeredGridLayoutManager(瀑布流)
    • 可以自定义,继承:RecycleView.LayoutManager
  • Adapter:将数据和RecycleView进行关联

    • 负责提供数据和创建列表项(Item) 视图

      • 比如:从数据中读取string, 将文字设置到item的view上
    • 数据和视图的媒介

    • 当数据发生变化时,管理数据的创建、更新、添加、删除

    • RecyclerView.Adapter

      适配器充当数据和RecyclerView之间的桥梁。它负责为数据集中的每个项目创建和管理视图。它为每个项目视图创建视图持有者(ViewHolder),以便在用户滚动列表时高效地重用视图。

      适配器对于处理数据的变化、更新、添加和删除非常重要。它在数据集发生变化时通知RecyclerView,以便RecyclerView相应地更新显示。

  • Viewholder:持有显示1个item的视图信息

    • 负责保存列表项视图的引用,以便在需要时快速访问视图
    • Layout在xml文件中进行声明
    • 可以包含可以点击的元素
    • 由LayoutManager进行摆放

使用步骤

  1. 添加RecycleV的依赖到build.gradle文件中。

    1
    2
    3
    4
    5
    dependencies{
    ...
    compile 'com.android.support:recyclerview-v7:26.1.0'
    ...
    }
  2. Layout在xml文件中进行声明

    1
    2
    3
    4
    5
    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rv_demo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />
  3. 为每一个Item创建xml布局

    recycleview_item2.xml文件

    定义了其中的一行

  4. 继承RecyclerView.Adapter
    三个必须实现的方法:
    onCreateViewHolder() 表示布局需要创建的viewHolder是哪个

    inBindViewHolder() 表示在绑定的时候如何去设置文案

    getItemCount() 表示这个列表的大小是多少

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    class DemoAdapter : RecyclerView.Adapter<DemoViewHolder> {

    /** 保存数据的列表 */
    private val demoList: List<ItemBean>

    constructor(demoList: List<ItemBean>) {
    this.demoList = demoList
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DemoViewHolder {
    val view: View =
    LayoutInflater.from(parent.context).inflate(R.layout.recycleview_item, parent, false)
    return DemoViewHolder(view)
    }


    override fun onBindViewHolder(holder: DemoViewHolder, position: Int) {
    val itemBean = demoList[position]

    itemBean.coverUrl?.let {
    holder.ivCover?.setImageResource(it)
    }

    itemBean.title?.let {
    holder.tvTitle.text = it
    }

    itemBean.content?.let {
    holder.tvContent.text = it
    }
    }

    override fun getItemCount(): Int {
    return demoList.size
    }
    }
  5. 继承RecyclerView.ViewHolder(看实例代码的DemoViewHolder 每个属性对应单个item的属性)

  6. 在Activity的onCreate()中,获取RecycleView,并且为它设置Adapter和LayoutParams

    1
    2
    3
    4
    5
    6
    7
    8
    // 1. 找到获取RecyclerView
    mRecyclerView = findViewById(R.id.recyclerview);
    // 2. new一个adapter,第二个参数为构造的数据
    mAdapter = new WordListAdapter(this, mWordList);
    // 3. 创建的adapter设置给RecyclerView
    mRecyclerView.setAdapter(mAdapter);
    // 4. 设置LayoutManager
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

ellipsize和maxLines

控制...出现的位置

短文字也能居中的方法

将demo的wrap_content改成match_parent

动画

帧动画

1.在XML中创建帧动画(frame_anim.xml)

oneshot属性控制是否循环播放

1
2
3
4
5
<animation-list mins:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android: drawable="@drawable/framel" android:duration="200" />
<item android:drawable="@drawable/frame2" android:duration="200" />
<item android: drawable="@drawable/frame3" android:duration="200" />
</animation-list>

2.将动画设置给指定的View

1
2
3
4
5
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/frame_anim" />

3.通过代码控制播放

1
2
3
4
5
6
7
8
9
10
11
// java
ImageView imageView = findViewById(R.id.imageView);
imageView.setBackgroundResource(R.drawable.frame animation);
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getBackground()
animationDrawable.start();

// kotlin
private fun showFrameAnimLoading() {
frameAnimLoading = findViewById(R.id.iv_loading)
(frameAnimLoading?.background as? AnimationDrawable)?.start()
}

补间动画

平移动画

1
2
3
4
<translate mIns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="100"
android:duration="1000" />

缩放动画

1
2
3
4
5
6
7
8
9
10
<scale mIns: android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:toXScale="2"
android:fromYScale="1"
android:toYScale="2"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000" />
<!-- from/to 从那放缩到哪 -->
<!-- pivotX/Y 表示图的中心点位置 -->

动画集合(旋转、位移、透明度、缩放动画的集合)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate interpolator"
android:shareInterpolator="true" >
<rotate
android:duration="1000"
android:fromDegrees="0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toDegrees="360" />
<!-- 从多少度旋转到多少度 -->
<alpha
android:duration="2000"
android:fromAlpha="1.0"
android:toAlpha="0.1" />
<!-- 从多少消失到多少持续时间多久 -->
</set>

监听器AnimationListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate_animation)
animation.setAnimationListener(new Animation.AnimationListener () {
@Override
public void onAnimationStart(Animation animation) {
// 动画开始时执行的操作
}
@override
public void onAnimationEnd(Animation animation) {
// 动画结束时执行的操作
}
@override
public void onAnimationRepeat(Animation animation) {
// 动画重复时执行的操作
}
});

imageView.startAnimation(animation);

属性动画

直接对组件的属性进行改变

**定义:**改变对象的属性值来实现动画效果。需要一个属性名称(如"alpha", "translationX"等),一个或多个关键帧(表示属性值在某个时间点的取值)以及一个插值器(用于控制属性值在关键帧之间的变化规律)

**范围:**可以作用于任何对象

ValueAnimator

  • 不直接操作对象的属性,而是计算一系列值,这些值可以用于为对象的属性提供动画效果。ValueAnimator通过设定起始值、结束值、持续时间和插值器等参数,实现值的动态变化。

  • 使用方法

    1. ​ 调用ofInt(), ofFloat()或ofObject()静态方法创建ValueAnimator实例

      1
      ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
    2. 配置动画:时间、动画次数、动画速度等

      1
      2
      valueAnimator.setDuration(1000);	// 设置动画持续时间为1s
      valueAnimator.setInterpolator(new LInearInterpolator()); // 设置插值器为线性插值器
    3. 监听值的变化

      1
      2
      3
      4
      5
      6
      7
      8
      valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimatonUpdate(ValueAnimator animator) {
      int currentValue = (int) animaton.getAnimatedValue();
      // 将 currentValue 应用到对象的属性上,例如更行 ProgressBar 的进度
      progressBar.setProgress(currentValue);
      }
      })

ObjectAnimator(简单了解即可

  • 继承自ValueAnimator,并添加了对目标对象属性的支持。它可以对目标对象的属性进行动画操作,例如平移、旋转、缩放等。

  • 使用方法

    1. target: 需要动画的View; translationX:需要修改的属性;初始值、结束值

      1
      2
      3
      4
      ObjectAnimator animator = ObjectAnimator.ofFloat(target, "translatonX", 0f, 200f);
      animator.setDuration(500);
      animator.setInterpolator(new AccelerateDecelerateInterpolator());
      animator.start();
    2. 给自定义View添加

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class MyView extends View{
      private floate myProperty;
      get...
      set...{
      ...
      invalidate();
      }
      }

      ObjectAnimator animator = ObjectAnimator.ofFloat(myView, "myProperty", 0f, 100f);
      animator.setDuration(500);
      animator.start();

插值器(51:38

体验插值器的网站Interpolator (inloop.github.io)

过度绘制&布局优化

布局显示的过程

  1. inflate

    将XML格式的layout文件实例化为相应的View对象

  2. measure

    从根节点开始计算所有VIew的尺寸。会调用每个View的measure方法(可能会调用多次)。

  3. layout

    从根节点开始计算所有View的位置。(根据measure中确定的尺寸)

  4. draw

    绘制View

影响UI效率的因素

  1. View太多

    更多的inflate

    更长的drawing时间

  2. 布局太深

    更多的measure和layout

  3. 图片&背景

    图片资源过大

    图片缩放耗时

    过度绘制

  4. 频繁刷新UI

    占用cpu资源

    界面卡顿,交互反应慢,甚至造成ANR

过度绘制

  • 真彩色:没有过度绘制
  • 蓝色:过度绘制1次
  • 绿色:2次
  • 粉色:3次
  • 红色:4次或更多

优化实践

  1. 优化布局:减少View

    尽可能减的减少控件的使用,(使用drawbleLeft)

  2. 使用更合适的布局容器

  3. 使用<ViewStub>标签

    不需要立即显示的视图,可以使用该标签对其进行延迟加载(在代码中判断)

    1
    2
    3
    4
    5
    <ViewStub
    android:id="@+id/vs"
    android:layout="@layout/layout_example"
    anroid:layout_width="match_parent"
    anroid:layout_height="match_parent"/>
    1
    2
    3
    4
    5
    6
    7
    // 获取ViewStub
    ViewStub viewStub = findViewById(R.id.vs);
    if(/* 某个条件成立*/) {
    View inflatedView = viewStub.inflate();
    // 此时, ViewStub已经替换为Layout_example.xml中定义的布局
    // inflatedView 是替换后的布局的根视图
    }
  4. 使用<inclued> 标签

    将公共布局抽取到独立的文件中,并通过该标签进行引用,以减少视图层级和代码重复

  5. 使用<merge> 标签

    对于包含多个子视图的自定义视图,可以在根布局中使用该标签,减少视图层级,从而减少过度绘制。

过度绘制

检查工具

作业

  • 标题: 2023百度移动端lec2-lec4
  • 作者: SYuan03
  • 创建于 : 2023-07-11 18:57:37
  • 更新于 : 2024-03-10 20:02:52
  • 链接: https://bblog.031105.xyz/posts/2023-Summer-Courses-百度移动端/2023百度移动端lec2-lec4.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论