安卓开发基础知识 part1


布局类型

  • FrameLayout 帧布局 最简单的布局

    ​ 叠放 gravity

  • LinearLayout 线性布局 左右排列 或 上下排列

    ​ 横向或者纵向 orientation horizontal vertical

  • RelativeLayout 相对布局 A B 之间有相对关系

  • ConstraintLayout 约束布局

    -> VIewGroup -> View

LinearLayout

线性布局(横向或者纵向)

  • orientation:设置排列方式 默认横向

    • Horizontal 横向排列

    • Vertical 纵向排列

  • weight:设置子控件占据父容器剩余空间的位置

FrameLayout

帧布局 不存在层级嵌套

第一个在最内层,后添加的在外面一层

  • 外间距:margin 控件和父容器之间的额间距

  • 内间距: padding 控件和自己内容之间的间距

ViewGroup.LayoutParams

  • width
  • height
  • MATCH_PARENT
  • WARP_CONTENT

View.MarginLayoutPrarms : ViewGroup.LayoutParams

  • leftMargin - startMargin : 统一表示各个国家的语言顺序
  • topMargin
  • rightMargin - endMargin
  • bottomMargin

FrameLayout.LayoutParams : ViewGroup.MarginLayoutPrarms

  • gravity

LinearLayout.LayoutParams

  • gravity : 父容器使用 设置容器内部子控件的对齐方式

    left start top right end bottom center center_horizontal center_vertical

  • layout_gravity : 子控件使用 设置子控件在父控件中的相对位置,如果父容器使用了gravity 子控件的优先级最高

  • weight :权重 设置子控件占据父容器剩余空间的比例 1:1 平分

RelativeLayout 相对布局

RelativeLayout.LayoutParams -> ViewGroup>MarginLayoutParams -> View.LayoutParams

  • 和父容器之间的位置关系
    • ALIGN_PARENT_BOTTOM 和父容器的底部对齐
    • ALIGN_PARENT_END 和父容器的右边对齐
    • ALIGN_PARENT_LEFT 和父容器的左边对齐
    • ALIGN_PARENT_RIGHT 和父容器的右边对齐
    • ALIGN_PARENT_START 和父容器的左边对齐
    • ALIGN_PARENT_TOP 和父容器的顶部对齐
    • CENTER_IN_PARENT 在父容器的中心位置
  • 和兄弟控件之间的位置关系
    • ABOVE 在某个控件的上面
    • BELOW 在某个控件的下面
    • END_OF 在某个控件的右边
    • START_OF 在某个控件的左边
    • ALIGN_BASELINE 和某个控件的基准线对齐
    • ALIGN_BOTTOM 和某个控件底部对齐
    • ALIGN_END 和某个控件右边对齐
    • ALIGN_START 和某个控件右边对齐
    • ALIGN_TOP 和某个控件顶部对齐

ConstraintLayout 约束布局

  • Start_toStartOf: 左边和某一个控件的左边对齐 父控件:parent 子控件:id
  • End_toEndOf
  • Match_constraint 匹 配约束,尺寸由约束来确定 = 0dp
  • Top_toTopOf
  • Bottom_toBottomOf

界面布局相关知识

  • 什么是View?

    • 视图 看得见的东西 单个View
  • 什么是ViewGroup?

    • 容器 可以容纳很多个View 包含多个视图

    • 每种容器都有自己独有的摆放方式

    • XML标记语言

      <LinearLayout 标签的属性>
          <!--子控件-->
      	<Button></Button> -> <Button 控件的属性/> 
          <!--如果没有子控件,可以简化为以下的形式-->
          <Button 控件的属性 />
      </LinearLayout>    
      
      • 设置xml文件中控件的尺寸

        android:layout_width=“match_parent” 设置控件的宽度

        android:layout_heiht=“match_parent” 设置控件的高度

        • match_parent : 匹配父容器 和父容器的宽度或者高度一致
        • warp_content : 包裹内容 由内容来定
        • 固定值 android:layout_heiht=“100dp”
          • 容易出错的情况:
            • 父容器使用warp_content, 子控件使用match_content, 导致无法确定控件的尺寸
    • 界面显示:

      • 1.计算子控件和容器的尺寸
      • 2.渲染
      • 3.加载
  • 如何找到xml中的控件

    • 给控件添加 id android:id = “@+id/black_view” blackView
      • 命名时如果有多个单词组成,只用_连接,小写
  • 如何确定一个控件的约束是否完整

    • 确定一个控件在界面中的位置由4个元素组成(x,y,width,height)
GuideLine 导航线
  • Vertical

  • Horizontal

    • 固定值

    • 百分比

Chains 横向和纵向链接
  • chain style
    • spread(默认) 均分
    • spread inside 中间均分
    • packed 中间挤满,两边均分
Ratio 比例 宽:高

设置宽高比

w:宽度不变

h:高度不变

如何更改控件的id

选中控件 -> 找到属性里面的id -> 改为新的id -> 弹出的提示框中 scope: current file -> refactor

图片资源保存到什么位置?

res -> drawable

图片资源名称只能使用小写字母,如果有多个单词组成使用_ eg:icon_cat

显示图片使用ImageView

图片拉伸:scaleType:fitXY centerCrop

如何引用系统的资源 -> 整数

每一个资源添加添加到项目中,会给它们分配一个整数,这个整数用来唯一表示这个资源

如何通过代码给图片设置资源

imageView.setImageResource(R.drawable.hema)

如何控制一个控件的显示和隐藏

visibility:

  • View.VISIBLE 控件可见
  • View.INVISIBLE 控件还在,但不可见
  • View.GONE 控件消失
怎么获取容器中的所有控件
  • 获取容器

    val container = findViewById<ConstraintLayout>(R.id.container)
    
  • 使用childCount获得子控件数,通过getChildAt 获得每个子控件,保存在数组中

    //保存所有的图片控件
        private val allViewList = mutableListOf<ImageView>()
    
    //获取所有的图片控件
    for (i in 0 until container.childCount) {
        val imageView = container.getChildAt(i) as ImageView
        allViewList.add(imageView)
    }
    
怎么将数据关联起来或将多个数据封装为整体

将数据封装到一个类中

  /**
   * 用来封装每一个图标的信息
   * 图片控件
   * 图片资源id
   */
  class Model(
      val imageView: ImageView,
      val resId: Int
  )
打乱数组里的元素

使用shuffle方法

//打乱数组的顺序
allViewList.shuffle()
怎么延时操作

使用定时器进行延时

Timer().schedule(object : TimerTask() {
            override fun run() {
                TODO("Not yet implemented")
            }
        }, 500)

注意:1.安卓中主线程是用来显示界面的,子线程没有权限操作主界面

​ 2.注意可能出现的空指针异常

使用runOnUiThread切换到主线程

子线程中不能操作UI相关的事情,需要切换到主线程才能进行操作

使用翻转动画
  • 添加翻转动画
//折叠翻转动画
@SuppressLint("Recycle")
private fun addFilpAnimation(target: View) {
    //绕y轴旋转180度
    ObjectAnimator.ofFloat(target, "rotationY", 0f, 180f).apply {
        duration = 500
        start()
    }
}
  • 调用翻转动画
addFilpAnimation(lastSelectedModel!!.imageView)
  • 使用定时器能让动画更加流畅
 else {
            //图片不相同
            runOnUiThread {
                Timer().schedule(object : TimerTask() {		// 250毫秒以后再更改图片背景 -> 
                    override fun run() {
                        runOnUiThread {		//和UI相关的要放在主线程中运行
                            model.imageView.setImageResource(R.drawable.icbg)
                            lastSelectedModel!!.imageView.setImageResource(R.drawable.icbg)
                            lastSelectedModel = null		//不要提前设置为null,会出现空指针异常
                        }
                    }
                }, 250)
                addFilpAnimation(model.imageView)		//开启翻转动画
                addFilpAnimation(lastSelectedModel!!.imageView)
            }
        }
        timer = null    //定时器任务完成后,再空
    }
}, 500)
MVP设计模式
  • M Model 模型层 封装数据
  • V View -> Activity和其对应的layout布局文件 为了与layout布局文件交互 ,需要实现定义好的接口
  • P Persenter 展示层 通过接口中的属性和方法来和View进行交互
数据类

只有属性的类

data class LinkModel(
    val imageView: ImageView,
    val resId: Int
)
MVP中接口里面定义什么方法?

数据改变了,需要通知Activity做什么,就定义什么方法

interface ILinkView {
    //通知界面切换图片
    fun changeImage(target: ImageView, resId: Int)
    //通知界面更改显示的状态
    fun changeVisibleState(target: ImageView, visible: Boolean)
}
实现围绕y轴翻转动画、

of后的类型是什么,看动画改变的是什么属性

fun startFilpAnimation(view: View) {
    //of后的类型,看动画改变的是什么属性
    ObjectAnimator.ofFloat(
        view,			//给谁添加动画
        "rotationY",	//改变什么属性
        0f,				//改变的值
        180f
    ).also {
        it.duration = 500L  //动画持续的时间
        it.start()
    }

触摸事件

界面和布局文件是怎么关联的?
  • layout -> activity_main.xml 负责静态界面的布局

  • Activity -> MainActivity 负责界面的具体显示和生命周期

  • 通过setContentView(布局文件的id) 将layout布局文件显示到Activity中

  • 内容和界面的关系

    • 老版本:一个Activity管理一个界面 (一台电视机,只播放一部电影)

    • 新版本:全局只有一个Activity,使用Fragment管理每一个界面,切换界面只需要切换内容即可(一个电视机可以切换很多台)

界面的层次
  • 界面的层级关系

window -> status bar -> decor view -> action bar + Container -> 自己的内容

  • 窗口 Window
    • 状态栏 Status bar
    • 装饰层 Decor View
      • 导航栏 Action bar
      • 内容 Container
如何监听触摸事件
  • 重写Activity提供的onTouchEvent方法

  • 系统使用MotionEvent将触摸的事件封装起来

    • getAction 获得具体的事件
    • ACTION_DOWN 刚刚触摸到界面/按下去那刻
    • ACTION_MOVE 手在屏幕中连续滑动
    • ACTION_UP 抬手/离开屏幕那一刻
    • ACTION_CANCEL 被其他应用打断 取消这个事件
    • getX() getY() 获取触摸点的坐标
  • 事件的传递方式

    • 触摸事件的传递方式

      • 触摸事件是由Windows来监听,并且负责传递
      • decorView -> content -> 容器 -> 子容器 -> 子控件1 -> 子控件2 -> 子控件3
    • onTouchEvent方法的返回值

      • true 表示自己把这个事件消费了/处理了 后面就不会继续传递
      • false 表示自己没有消费 事件继续传递
    • 这个方法会被多次重复调用

      • 尽量不要在这个方法内部创建共享的对象或者代码块
    • 查找关联界面中的控件时容易犯的错

      • 界面还没有关联,就提前去获取界面里面的控件

        p9ycaon.png

      • 必须在界面后访问

        p9ycUds.png

        获取actionBar、statusBar、内容的高度
      • event.x event.y 是相对与window窗口的坐标位置

        • 需要将坐标转化为相对于内容视图 event.y - 状态栏 - 导航栏
      • Resource:管理程序的资源 color string drawable theme style

        • DisplayMetrics 管理屏幕显示的参数
          • widthPixels 屏幕的宽度
          • heightPixels 屏幕的高度(可用的宽度:导航栏 + 内容容器) (不包括状态栏)
          • density 屏幕的密度 (每一个物理点显示多少个)
            • 1x 一个点显示1个像素 160dpi 160px
            • 2x 一个点显示2个像素 160dpi 320px
            • 3x 一个点显示3个像素 160dpi 480px
      • Rect封装矩形区域 left top right bottom

      • Point 封装坐标 x y

    • 获取可用屏幕的高度

    //获取可用的屏幕高度 导航栏 + 内容容器
    val availableHeight =  resources.displayMetrics.heightPixels
    
    • 获取状态栏的高度
    //获取decorView的矩形区域 left right top bottom
    val rect = Rect()
    window.decorView.getWindowVisibleDisplayFrame(rect)
    //状态栏的高度
    val statusbarHeight = rect.top
    val actionBarHeight = window.findViewById<ViewGroup>(Window.ID_ANDROID_CONTENT).top
    
    • 获取内容的高度
    //获取内容的高度
    val actionBarHeight = window.findViewById<ViewGroup>(Window.ID_ANDROID_CONTENT).top
    
  • 当给父容器添加setOnTouchEvent事件,得到的x,y坐标就是相对于父容器的了

  • onCreat方法里面不能直接获取空间的尺寸 (宽、高)

    • 当系统需要启动界面前,先调用这个界面的onCreate方法,这个方法里面就是确定这个界面有哪些控件,当界面确定之后,再告诉系统去渲染(绘制)界面,渲染完毕,才展现在我们面前,所以在渲染之前是无法获取控件的尺寸的

    • 为什么在onCreat方法里面可以获取尺寸?

      • 当你去触摸界面时,界面已经展现在我们眼前了(绘制完毕了),尺寸位置已经确定
    • 如果想在onCreate方法里面获取控件的尺寸,只能监听控件即将被绘制的事件

    //监听控件即将被绘制的事件
    window.decorView.viewTreeObserver.addOnPreDrawListener {    
        mHeight = barHeight()
        true    //继续绘制 false 停止绘制
    }
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值