2024年安卓最全【Kotlin】关于Android事件传递的整理,2024年最新Android面试真题解析火爆全网

最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    android:textSize="20sp" />

</com.kongqw.view.ScrollViewPager>




写完布局我们要重写`onMeasure`和`onLayout`方法,开始对布局测量、排布。  

我们这里是纵向排布。



/**

  • 测量

*/

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec)

for (index in 0 until childCount) {

    measureChild(getChildAt(index), widthMeasureSpec, heightMeasureSpec)

}

}

/**

  • 布局 纵向布局

*/

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {

var top = 0

var bottom = 0

for (index in 0 until childCount) {

    val childView = getChildAt(index)

    bottom = top + childView.measuredHeight

    childView.layout(0, top, childView.measuredWidth, bottom)

    top = bottom

}

mBottomBorder = bottom

}




写到这里运行程序,应该是可以看得到第一个页面了,但是滑动没有任何反应,我们需要重写`onTouchEvent`方法,让View可以根据手指的滑动而滚动,这里需要监听event的`ACTION_DOWN`、`ACTION_MOVE`、`ACTION_UP`、`ACTION_CANCEL`状态,通过`ACTION_MOVE`记录手指每次纵向移动的距离,在监听到`ACTION_UP`、`ACTION_CANCEL`的时候,判断滑动位置,然后滚动到哪个页面。这样,一个简单的页面滑动就实现了。



### scrollBy、scrollTo



提到滚动,就不得不提到两个方法,`scrollBy`和`scrollTo`,值得注意的是,通常我们一种面向对象的思想,想让谁滚动,谁就调用自己的scroll就行了,但是,这里的`scrollBy`和`scrollTo`针对的是自己子View的运动,说白话了,就是老爸要管理儿子运动的。  

`scrollBy`是控制一次滚动多少,`scrollTo`是控制滚动到哪里。



我们这里自定义了ScrollViewPager,页面内容都写在ScrollViewPager内部,所以,我们控制滚动,就是在控制ScrollViewPager内部的子View滚动,所以,直接调用`scrollBy`和`scrollTo`即可。



### Scroller



现在滑动没有问题了,但是手指一松开,View 会瞬间移动到指定位置,体验不太好,我们想要View的滚动有一个顺滑的过程,这就又不得不再提到一个`Scroller`类,他可以帮助我们完成动画的平缓过度。



通过`Scroller`的`startScroll`来初始化运动的起始位置、结束位置和运动时间,然后调用`invalidate()`开始处理,这里会一直回调`View`的`computeScroll`方法,是一个空方法,需要我们自己在这里自己依据`Scroller`的`computeScrollOffset()`判断移动是否完成,然后调用`scrollTo`来完成平滑移动处理。



到这里,View就可以实现上下滑动,并平滑过渡了,接下来来处理事件的分发问题。  

我们想要实现的目标是,当我们上下滑动的时候,可以滚动页面,要将事件拦截。  

当我们在子控件上左右滑动的时候,可以将事件先交给子控件处理。那么我们就可以重写`ScrollViewPager`的`onInterceptTouchEvent`方法,在`ACTION_MOVE`的时候判断滑动方向,如果是上下滑动,则返回true,将事件拦截即可。



下面是自定义`ScrollViewPager`源码(Kotlin代码):



package com.kongqw.view.ScrollViewPager

import android.annotation.SuppressLint

import android.content.Context

import android.util.AttributeSet

import android.util.Log

import android.view.MotionEvent

import android.view.ViewConfiguration

import android.view.ViewGroup

import android.widget.Scroller

/**

  • Created by Kongqw on 2018/3/29.

  • ScrollViewPager

*/

class ScrollViewPager(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {

/**

 * 手指按下位置

 */

private var mDownX = 0.0F

private var mDownY = 0.0F



/**

 * 手指移动后的位置

 */

private var mMoveX = 0.0F

private var mMoveY = 0.0F



/**

 * 手指最后移动位置

 */

private var mLastX = 0.0F

private var mLastY = 0.0F



/**

 * View 上边界

 */

private val mTopBorder = 0



/**

 * View 下边界

 */

private var mBottomBorder = 0



/**

 * 滑动处理

 */

private val mScroller: Scroller = Scroller(context)



/**

 * 事件是否拦截

 */

private var isIntercept = false



/**

 * 最小移动单位

 */

private val mScaledtouchslop = ViewConfiguration.get(context).scaledTouchSlop



companion object {

    private val TAG: String = ScrollViewPager::class.java.simpleName

}



/**

 * 测量

 */

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

    super.onMeasure(widthMeasureSpec, heightMeasureSpec)

    for (index in 0 until childCount) {

        Log.i(TAG, "测量第 $index 个控件大小")

        measureChild(getChildAt(index), widthMeasureSpec, heightMeasureSpec)

    }

}



/**

 * 布局  纵向布局

 */

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {

    var top = 0

    var bottom = 0

    for (index in 0 until childCount) {

        val childView = getChildAt(index)

        bottom = top + childView.measuredHeight

        Log.i(TAG, "布局第几个View [0, ${top}, ${childView.measuredWidth}, ${bottom}]")

        childView.layout(0, top, childView.measuredWidth, bottom)

        top = bottom

    }

    mBottomBorder = bottom

    Log.i(TAG, "View 高度 $height")

}



override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {



    val touchX = ev?.rawX

    val touchY = ev?.rawY



    when (ev?.action) {



        MotionEvent.ACTION_DOWN -> {

            mDownX = touchX!!

            mDownY = touchY!!

            isIntercept = false

        }

        MotionEvent.ACTION_MOVE -> {

            mMoveX = touchX!!

            mMoveY = touchY!!

            val dx = Math.abs(mMoveX - mDownX)

            val dy = Math.abs(mMoveY - mDownY)

// if(dy > dx){

// isIntercept = true

// }

            isIntercept = (dy > dx)

        }

        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {

            isIntercept = false

        }



    }



    mLastX = touchX!!

    mLastY = touchY!!



    return isIntercept

    // return super.onInterceptTouchEvent(ev)

}



@SuppressLint("ClickableViewAccessibility")

override fun onTouchEvent(event: MotionEvent?): Boolean {



    val touchY = event?.rawY



    when (event?.action) {

        MotionEvent.ACTION_DOWN -> {

            Log.i(TAG, "ACTION_DOWN")

            // 获取手指按下的位置

            mDownY = touchY!!

            return true

        }

        MotionEvent.ACTION_MOVE -> {

            Log.i(TAG, "ACTION_MOVE")

            // 获取手指移动后的位置

            mMoveY = touchY!!

            // 计算手指在Y轴移动距离

            // val dY = Math.abs(mLastY - mDownY)

            val dY = mLastY - mMoveY





            when {

                scrollY < mTopBorder -> {

                    // 向下已经划出上边界

                    Log.i(TAG, "向下已经划出上边界")

                    scrollBy(0, dY.toInt() / 5)

                }



                scrollY + height > mBottomBorder -> {

                    // 向上已经划出下边界

                    Log.i(TAG, "向上已经划出下边界")

                    scrollBy(0, dY.toInt() / 5)

                }



                else -> {

                    // 移动

                    scrollBy(0, dY.toInt())

                }

            }



            // 刷新页面

            invalidate()



            mLastY = mMoveY



        }

        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {

            Log.i(TAG, "ACTION_UP  View 纵向滑动了 $scrollY")



            when {

                scrollY <= mTopBorder -> {

                    // 向下已经划出上边界

                    Log.i(TAG, "向下已经划出上边界")

                    mScroller.startScroll(0, scrollY, 0, -scrollY)

                    invalidate()

                }



                scrollY + height >= mBottomBorder -> {

                    // 向上已经划出下边界

                    Log.i(TAG, "向上已经划出下边界")

                    val dy = mBottomBorder - scrollY - height

                    mScroller.startScroll(0, scrollY, 0, dy)

                    invalidate()

                }



                else -> {

                    // 移动

                    val page = computePageByScrollY(scrollY)

                    Log.i(TAG, "滑动到第 $page 页")

                    mScroller.startScroll(0, scrollY, 0, height * page - scrollY)

                    invalidate()

                }

            }

        }

    }



    mLastY = touchY!!



    return super.onTouchEvent(event)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题全套解析,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。

image

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题全套解析,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。

[外链图片转存中…(img-TkcVkGbt-1715751893132)]

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-7D34727D-1715751893132)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值