从源码角度分析View的加载过程

subsampling-scale-image-view加载长图源码分析总结 subsampling-scale-image-view源码分析背景介绍使用源码分析总结参考 背景 对于安卓开发人员,最头疼的问题就是内存问题了,而内存问题又当属bitmap最头疼,虽然说现在市面上已经有越来越多成熟的图片加载框架,像Fresco,Glide,它们也确实帮我更好地管理了图片的内存,生命周期等,但是还是有一个比较棘手的问题,那就是大图长图的加载,动辄750 * 30000的长图,如果... 阅读详情

 

本文是依据Android 8.1.0的相关源码进行分析。

一、setContentView的如何加载布局?

通常Activity的onCreate里面都需要写上setContentView,那么就从Activity入手,找到setContentView,如下:

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

从上面可以看出,调用的是Window的setContentView方法,这个Window是一个抽象类,他是子在attach方法中被创建的:

mWindow = new PhoneWindow(this, window, activityConfigCallback);

可以看出,PhoneWindow是Window的实现类,这里可以明确出他是Window唯一实现类,找到实现类的setContentView方法:

    @Override
    public void setContentView(int layoutResID) {

        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

如果mContentParent是否为空,则执行installDecor,移除了一些不重要的方法:

    private void installDecor() {
        //创建DecorView,将DecorView添加至Window
        if (mDecor == null) {
            mDecor = generateDecor(-1);
        } else {
            mDecor.setWindow(this);
        }
        //创建mContentParent,并且添加至DecorView
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
        }
    }

创建DecorView:

    protected DecorView generateDecor(int featureId) {
        return new DecorView(context, featureId, this, getAttributes());
    }

这里需要知道的是DecorView继承自FrameLayout布局。

创建ContentParent,代码很长,只保留核心内容:

     protected ViewGroup generateLayout(DecorView decor) {
        //1.获取layoutparams
        WindowManager.LayoutParams params = getAttributes();
        //2.加载根布局
        if (根据设置主题加载对应的xml,很多逻辑判断) {
            layoutResource = R.layout.screen_simple;
        }
        //3.设置DecorView变化监听
        mDecor.startChanging();
        //4.将根布局加载到DecorView中
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
        //5.在Window中找到id ID_ANDROID_CONTENT,即下面的FrameLayout
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

        return contentParent;
     }

在上面第二步中加载的根布局如下,其中FrameLayout就是设置setContentView的根布局,后面会提到,ViewStub是与actionbar相关属性。

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:fitsSystemWindows="true"
         android:orientation="vertical">
         <ViewStub android:id="@+id/action_mode_bar_stub"
                   android:inflatedId="@+id/action_mode_bar"
                   android:layout="@layout/action_mode_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:theme="?attr/actionBarTheme" />
         <FrameLayout
              android:id="@android:id/content"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:foregroundInsidePadding="false"
              android:foregroundGravity="fill_horizontal|top"
              android:foreground="?android:attr/windowContentOverlay" />
     </LinearLayout>

在上面的WindowPhone中有段如下代码:

mLayoutInflater.inflate(layoutResID, mContentParent);

layoutResID就是setContentView的xml布局mContentParent就是上面创建的contentParent,这行代码就是将xml父布局FrameLayout中。

总结下:

为了验证上面的情况新建一个项目打开Android Studio 新建一个项目,XML页面如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.myapplication.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:text="啦啦啦"/>

</RelativeLayout>

这是运行项目,打开Android Device Monitor——>hierarchy viewer:

这时候我们可以更新清晰直观的了看到整个页面View的结构图:

二、DecorView如何添加View?

DecorView是通过Window的setContentView的mDecor.setWindow(this);添加至Window中,布局的细节后面在讲。这里主要说的是上面的布局文件(R.layout.screen_simple)如何加到DecorView中。在上面的generateLayout方法中第四个备注的onResourcesLoaded方法就是加载的View布局,在DecorView找到对应的方法:

    void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {

         mDecorCaptionView = createDecorCaptionView(inflater);
         final View root = inflater.inflate(layoutResource, null);
         if (mDecorCaptionView != null) {

         } else {
             //直接添加到DecorView中
             addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
         }
         mContentRoot = (ViewGroup) root;
         initializeElevation();
     }

使用addView直接DecorView中,DecorView继承自FrameLayout,addView是ViewGroup中的方法,如下核心代码:

    public void addView(View child, int index, LayoutParams params) {
        //请求View重新绘制
        requestLayout();
        //刷新UI
        invalidate(true);
        //添加View动画和监听相关
        addViewInner(child, index, params, false);
    }

addView的详细部分下面再说明,现在对上面一、二部分进行一个大总结:

三、DecorView如何显示View?

这里按照上面的三步进行分析。

1、请求View重新绘制(requestLayout)

    public void requestLayout() {

        if (mMeasureCache != null) mMeasureCache.clear();

        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
            //获取ViewRootImpl,该对象是在内部类AttachInfo中被实例化
            ViewRootImpl viewRoot = getViewRootImpl();
            if (viewRoot != null && viewRoot.isInLayout()) {
                if (!viewRoot.requestLayoutDuringLayout(this)) {
                    return;
                }
            }
            mAttachInfo.mViewRequestingLayout = this;
        }

        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
        mPrivateFlags |= PFLAG_INVALIDATED;

        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
            mAttachInfo.mViewRequestingLayout = null;
        }
    }

    这里判断当前View是否正在进行布局流程,并且设置标志位,该标志位用于标记当前的View是否需要重新布局,接着调用 mParent.requestLayout();方法,进行该View的父布局的布局请求,层层递归,直到最顶层的DecorView,而DecorView又会把事件传递给ViewRootImpl,这是一种责任链设计模式,即不断向上传递该事件,直到找到能处理该事件的上级,这里的最终上级就是ViewRootImpl。DecorView和ViewRootImpl的关系是ViewRootImpl是实现View的绘制的类,里面有三个方法是关键,DecorView 是一个顶层 View,是应用的整个界面。ViewRootImpl中找到对应的方法:

    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            //检查是否在主线程
            checkThread();
            //设置标识位
            mLayoutRequested = true;
            //该方法如下
            scheduleTraversals();
        }
    }

在这里,调用了scheduleTraversals方法,这个方法是一个异步方法,最终会调用到ViewRootImpl的performTraversals方法,这也是View工作流程的核心方法,在这个方法内部,分别调用measure、layout、draw来进行View的三大工作流程。详情如下:

    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

这里重点关注mTraversalRunnable这个类,他implements Runnable这个类,执行doTraversal()方法,在该方法内部有调用了performTraversals()方法:

   void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

performTraversals代码十分长,核心方法如下:

    private void performTraversals() {
        performMeasure() ——> mView.measure
        performLayout() ——> mView.layout
        performDraw() ——> draw ——> drawSoftware ——> mView.draw ——> mView.draw(canvas);
    }

如下图:

总结:

requestLayout的流程如下:

requestLayout ——> scheduleTraversals ——> mTraversalRunnable ——> doTraversal ——> performTraversals ——> performMeasure ——> performLayout ——> performDraw

2、刷新UI(invalidate)

    public void invalidate(boolean invalidateCache) {
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }

invalidateInternal核心代码如下,删除了其余代码:

    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
                boolean fullInvalidate) {
                final ViewParent p = mParent;
                if (p != null && ai != null && l < r && t < b) {
                    //向父View进行进行刷新
                    p.invalidateChild(this, damage);
                }
            }
    }

由此可知,View的invalidate方法实质是将要刷新区域直接传递给了【父ViewGroup的invalidateChild方法】,这是一个从当前View向上级父View回溯的过程。找到ViewGroup的invalidateChild方法:

    public final void invalidateChild(View child, final Rect dirty) {
        ViewParent parent = this;
        do {
            //循环层层上级调用,直到ViewRootImpl会返回null
            parent = parent.invalidateChildInParent(location, dirty);
        } while (parent != null);
    }

这里会层层循环,直到parent为null就会跳出该循环,什么情况下为null呢?遍历到最顶层ViewGroup即ViewRootImpl,他最终返回null,如下:

    @Override
    public void invalidateChild(View child, Rect dirty) {
        invalidateChildInParent(null, dirty);
    }
    @Override
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
    	if (dirty == null) {
            invalidate();
            return null;
        } else if (dirty.isEmpty() && !mIsAnimating) {
            return null;
        }
        //内部会调用scheduleTraversals();
        invalidateRectOnScreen(dirty);

    	return null;
    }

invalidateRectOnScreen内部会调用scheduleTraversals(),最终调用performTraversals执行重绘,上面分析有。所以,View调用invalidate方法的实质是:层层上传到父级,直到传递到ViewRootImpl后会触发scheduleTraversals方法,然后整个View树就开始重新按照View的绘制流程进行重绘任务。在invalidate的过程中,如果View的大小没有发生改变,就不会执行Draw方法,如果是在子线程中请求绘制刷新UI需要使用postInvalidate方法。

3、添加View相关属性(addViewInner)

addViewInner是addView的最后一步,主要设置了一些回调和动画、焦点、监听等。

     private void addViewInner(View child, int index, LayoutParams params,
                boolean preventRequestLayout) {
          //将View添加到数组中,获取mChildrenCount
          addInArray(child, index);
          //将View添加到Window上
          child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
          //当有View被添加进来时候,会回调onViewAdded方法,可用于View添加监听
          dispatchViewAdded(child);
     }

这样经过以上三步就玩成了View的添加显示,整个加载显示过程流程如下:

 

下一篇将分析View具体的绘制过程,也就是performTraversals的具体流程。

 

 

uiview源码使用 立即下载

相关推荐

Kettle 连接 Oracle 数据库全流程指南

例如:C:\Oracle\product\19.0.0\dbhome_1\jdbc\lib\ojdbc8.jar 2. 替换 Kettle 驱动文件 将驱动文件复制到 Kettle 的 目录: 删除旧版本驱动:如 ojdbc14.jar 只能保留一个oracle驱动 重启 Kettle 以加载新驱动 二、配置数据库连接 1. 启动 Kettle 并新建转换 运行 (Windows)或 (Linux)。 新建转换(Transformation),添加 “表输入” 步骤,双击进入配置。 2.

qq_44724453的博客 3479

java view_通过Java代码来创建view的方法

一、简介需要了解的知识二、方法1)java代码创建view方法* 1、先建view对象View view= View.inflate(this, R.layout.activity01, null);* 2、在view中填充R.layout.activity01页面View view= View.inflate(this, R.layout.activity01, null);* 3、然后在vie...

weixin_33305182的博客 1407

Ceres Solver:从入门到使用

Ceres Solver是谷歌开源的C++非线性优化库,能够解决有约束或无约束条件下的非线性最小二乘问题。2010年之后大量的运用在谷歌的产品开发中,尤其在谷歌开源的cartographer中被大量的使用。 ceres可以在Linux,Windows,macOS,Andrioid,IOS系统进行安装使用,详情可查看下方的官网链接。 Ceres Solver 官网:http://ceres-solver.org/

非晚非晚的博客 1万+

重温View绘制原理(一)

1. View的知识前提 View的绘制是从上往下一层层迭代下来的:DecorView–>ViewGroup(—>ViewGroup)–>View,所以,在学习view的绘制原理前,我们来先看看DecorView。 1.1 DecorView的视图结构 Android 中 Activity 是作为应用程序的载体存在,代表着一个完整的用户界面,提供了一个窗口来绘制各种视图。每个a...

何武昭的专栏 1545

PRD撰写效率翻倍秘籍:我是如何用大模型+飞书文档搭建自动化工作流的

本文分享了如何利用大模型与飞书文档构建自动化工作流,以大幅提升PRD撰写效率。通过结构化需求输入、设计模块化提示词模板,并借助自动化脚本桥接数据与文档,产品经理可将繁琐的文档撰写工作自动化,从而将精力聚焦于产品战略与用户洞察。

weixin_28520495的博客 404

STM32G0/G4无刷电机硬件设计与FOC控制实现

无刷直流电机(BLDC)和永磁同步电机(PMSM)的矢量控制依赖于高精度电流采样、实时SVPWM调制与闭环PI调节等核心技术。其底层实现需兼顾电机本体建模、坐标变换(Clark/Park)、死区补偿及硬件资源约束。STM32G0系列凭借CORDIC协处理器与超低功耗特性,适用于成本敏感型有感FOC应用;而STM32G4集成运放、FMAC滤波器与高级定时器,可支撑高性能无感控制与多源传感融合。该技术广泛应用于机器人关节、智能云台、伺服驱动等场景,是嵌入式电机控制工程师必须掌握的工程化落地能力。

weixin_35751412的博客 118

Android中View绘制流程(源码)

日常开发中,我们经常碰到需要自定义View(包括自定义View和ViewGroup)的地方,并且在面试中也需要我们熟悉或者精通自定义View。毕竟有时候我们需要实现的效果,Android本身是没有提供的,就需要我们去自定义,掌握原理可以让我们在实际使用中更加得心应手。 一、View是如何被添加到屏幕上的 从Activity走起,我们日常是通过Activity的onCreate()方法中的 se...

Silicon_Valley 817

uniapp - H5人脸识别认证与活体检测功能(纯前端免费方案+微信sdk人脸识别)完整源码,微信公众号网页/h5端人脸识别功能人脸核身(微信方案提供后端spring boot+thinkphp源码

uniapp实现人脸认证,uniAPP h5手机拍照+人脸识别,免费人脸识别插件,前端人脸识别解决方案,uniapp H5人脸识别带前后摄像头,人脸识别在H5页面进行采集,微信公众号H5人脸核身,H5端人脸识别功能实现,免费h5人脸识别插件方案,微信公众号H5网页实现人脸识别,uniapp人脸监测,uniapp人脸生物监测,使用uniapp开发H5人脸采集功能/人脸识别功能,uniapp项目—h5端人脸采集功能实现,uniapp vue3人脸核身,H5活体检测认证,人脸认证张嘴摇摇头指引动作,人脸核身 微信

🏆 前端领域优质创作者 3808

认识Android中的ViewRootImpl和DecorView

PS:本文系转载文章,阅读原文可读性会更好些,原文链接: https://mp.weixin.qq.com/s/EGFHW7URuIv0HqwZWt09sg ps:源码是基于 android api 27 来分析的 ViewRootImpl 是用来测量、布局和绘制 View 用的,View 的测量、布局和绘制是从 Activity 的 makeVisible方法开始的,但是本篇文章重点不是具体讲这个(View 的测量、布局和绘制代码细节),而是讲对 ViewRootImpl和DecorView 认知。 1、

qq_37837621的博客 812

YOLOv11模型改进-模块-引入特征细化模块FRFN 解决小目标、遮挡等问题

FRFN 是一种专门设计的深度学习结构,旨在提高图像处理任务中的特征表示能力。它的核心设计理念是通过逐层细化和优化特征图,从而实现更高的分类和检测精度。1. 特征提取层:通过卷积层提取初始特征,并进行批量归一化以增强稳定性。2. 特征细化模块:在每个模块中,当前层特征图与前一层特征图进行融合,以强化特征表示。3. 跳跃连接:通过跳跃连接保留多尺度信息,帮助缓解深层网络中的信息丢失。4. 非线性激活:使用激活函数(如ReLU)增加模型的非线性能力。5. 输出层。

qq_64693987的博客 3333

【感知模块算法】障碍物detect+trace+prediction方向介绍

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、多维度看感知问题,体会复杂性二、障碍物/环境目标detect方向1.视觉目标检测方向(1)图像处理认知(2)视觉基础理论部分1、获取数据集---python网页爬虫、买数据、自己录数据、使用开源比赛的数据集2、opencv库的学习3、深度学习框架学习(3)视觉目标检测理论(1)目标检测的概念(2)目标检测的应用场景(3)现有目标检测框架原理及论文【这仅仅是我当初入门学习的框架~

qq_35635374的博客 2893

Android中Activity的setContentView方法分析

PS:本文系转载文章,阅读原文可读性会更好些,原文链接:https://mp.weixin.qq.com/s/sphTiuqVgPLFC0Yg2CyW0g ps:源码是基于 android api 27 来分析的 这一篇我们分析 Activity 的 setContentView 方法到底做了什么事情,有的读者可能心存疑虑,文章有的地方看不懂怎么办,之前我看文章的时候也是有这样的疑虑,目前我采取的办法有2种:(1)看不懂的地方可以先跳过,看完本篇文章后再 google 一下看不懂的地方;(2)看不懂的地方先

qq_37837621的博客 755

智慧园区——解读零碳智慧园区全域双碳管理建设方案【附全文阅读】

《零碳智慧园区全域双碳管理建设方案》为园区开发运营企业、政府部门及绿色能源服务商等提供系统性指导。方案基于"背景-理念-路径"框架,首先分析全球双碳趋势及我国园区高碳排放现状,明确零碳园区价值;其次提出"数字+绿色"双动力理念,构建数字底座与绿色能源体系;最后详细规划实施路径,包括碳排查、绿能规划、能效优化、碳交易等全流程管理,结合数字孪生技术实现可视化管控,助力园区实现碳中和目标。

cdfunlove的博客 206

「性能优化2.0」布局加载原理

「性能优化0」启动分类及启动时间的测量 「性能优化1」计算方法的执行时间 「性能优化2」异步优化 「性能优化4」布局加载原理 一、布局加载原理 这一小节我们从源码的角度来分析 View 是如何加载的。 我简单的绘了一张流程图,根据这张图配合接下来的源码开始我们的工作吧: 废话不多说,直接从 setContentView 作为切入点,分析 Activity 的布局加载原理。 1.1、Activ...

六号表哥 260

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

android中激活码的原理,自定义View从实现到原理(二)- 源码解析Activity的构成

自定义View从实现到原理(二)View的分发机制在自定义View中属于比较重要的一部分,在这以前,咱们有必要了解一下Activity的组成,而后从源码的角度分析View的事件分发机制。java源码解析Activity的构成咱们都知道,点击事件使用MotionEvent来表示的,在一个点击事件发生以后,首先会传到Activity,那么咱们首先要了解一下Activity的构成,在咱们写Activit...

weixin_39823017的博客 371

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

资源访问机制之资源定义与解析流程

转载请注明出处:http://blog.youkuaiyun.com/droyon/article/details/22429191 本文主要介绍一下问题: 1、android资源相关的简要介绍。2、xml文件,在android中的加载、解析过程。3、以layout文件为例,介绍layout文件是如何一步一步的被andrioid加载、解析、生成View树。 -----------------------

hailushijie的专栏 3348

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android 自定义View、ViewGroup(一)之工作原理

android自定义view ViewGroup

wuchuang 1106

自定义View之雷达图

点击上方“程序员大咖”,选择“置顶公众号”关键时刻,第一时间送达!作者:Jack921链接:https://www.jianshu.com/p/cbcf3054a0e9程...

<sdffdsfsdfdfs>sfsfsfsdfsdffds</sdfsDS>Fsd 313

从源码角度详细分析View的绘制流程

前言 源码分析基于api27即android8.1版本。 网上翻阅了很多篇view的绘制流程文章,基本全流程介绍的很少,或者中间有很大的断档不好衔接。 本文从源码角度,每个方法的调用和跳转说的比较详细。 文章比较长,因为是看源码,比较枯燥,可以分几次阅读。 文章的意义:帮助自己和他人,从源码的角度梳理流程。读者可以跟着文章的流程,自己也走一遍源码。看源码的作用我觉得主要是帮助我们更加深入的理解a...

安迪爸爸 436

学徒浅析Android——从setContentView()角度分析View、Window、Activity三者关系

本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布参考码源:Android Oreo 8.0.0工具:Layout Inspector 我们在Activity的onCreate()方法中设置setContentView(),但是一直不明白其中的原理,正好公司在开展技术交流活动,分到的课题是View、Activity、Window的关系,借这个机会梳理一番。Activity生命周期的...

lz8362的专栏 8022

从源码角度分析ViewStub 疑问与原理

一、提出疑问     ViewStub比较简单,之前文章都提及到《Android 性能优化 三 布局优化ViewStub标签的使用》,但是在使用过程中有一个疑惑,到底是ViewStub上设置的参数有效还是在其包括的layout中设置参数有效?如果不明白描述的问题,可以看下以下布局伪代码。 res/layout/main.xml <ViewStub androi

Android 4522

Android AdapterView View的复用机制 分析

对于ListView、GridView相信大家都不陌生,重写个BaseView,实现对于的几个方法,然后就完成了我们的界面展示,并且在大部分情况下,我们加载特别多的Item也不会发生OOM,大家也都明白内部有缓存机制,都遇到过ItemView复用带来的一些问题,比如异步加载图片,最终造成界面显示的混乱,我们一般会使用setTag,然后回调显示时,避免造成混乱。 设想1:拿ListView为例,如

Hongyang 4万+

Android自定义view之View的测量过程全解析

Android 应用层开发中绕不开自定义 View 这个话题,虽然现在 Github 上有形形色色的开源库供大家使用, 但是作为一名开发者而言,虽然不提倡重复造轮子,但是轮子都是造出来的。碰到一些新鲜的 UI 效果时, 如果现有的控件无法完成任务,那么我们就应该想到要自定义一个 View 了。 我们知道,在 Android 中 View 绘制流程有测量、布局、绘制三个步骤,它们分别对应 3...

qq_15327675的博客 1750

解决ViewPager设置高度无效问题,从源码角度分析并解决问题

解决ViewPager设置高度无效问题,从源码角度分析并解决问题 大家在开发中使用ViewPager做轮播之类的控件时,是不是会遇到当想设置它的高度时,怎么写都不生效,这其实是ViewPager的设计思想导致的,起初ViewPager就是为了做全屏的滑动切换,所以在它的源码中onMeasure中第一步就设置了自己的宽高 源码中已经设定了默认使用父View的宽高,我们真实的需求其实大多都是希望ViewPager根据自己的子View高度来自适应自己的高度 而我们遇到这个问题时,一般来说都是不知道问度娘… 当我们

L0VE_Iris的博客 1149

View源码分析之事件分发机制

前言 事件分发机制主要是为了处理用户触摸屏幕产生的事件,因为每个页面都是由多个View组合而成的,那么具体由谁来处理这个事件呢,接下来我们来分析一下。 概念 触摸事件也就是对MotionEvent事件的分发过程,即当一个MotionEvent产生以后,系统需要把这个事件传递给具体的view。MotionEvent包含触摸的动作、位置等;这个类里包含了一系列的事件,事件的类型有 触摸状态 具体动作 ACTION_DOWN 按下 手势开始 ACTION_UP 抬起 手势结束 ACTION

qq_28581471的博客 179

从Android 6.0源码的角度剖析View的事件分发机制

请尊重原创,转载请声明出处: 在从Android 6.0源码的角度剖析UI界面架构一文中,我们了解到Activity是Android的可视化界面,是用户与Android系统交互的窗口,也就是说每个Activity都对应着一个窗体,但窗体是一个抽象的概念,它的具体表现形式是视图。在Android中,窗体对应着Window类,视图对应着View类。Window是一个抽象类,它的具体实现是PhoneW...

老蒋也疯狂 1670
上一篇: 软键盘相关问题总结
下一篇: 从源码角度分析View的绘制流程
一杯清泉
博客等级 码龄11年 314粉丝 210原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值