【问题标题】:How does findViewById work?findViewById 是如何工作的?
【发布时间】:2019-01-18 20:18:12
【问题描述】:
package com.example.dell.helloworld;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void showToast(View view)
    {
        Toast t= new Toast(this);
        LayoutInflater inflater=getLayoutInflater();
        View v=inflater.inflate(R.layout.toast, (ViewGroup) findViewById(R.id.toastViewGroup));
        t.setView(v);
        t.show();


    }
}

来自安卓开发者网站 findViewById 搜索带有给定 id 的子视图。

在上面的代码中,谁是父视图,谁的子视图被搜索给定的id?

【问题讨论】:

    标签: android findviewbyid


    【解决方案1】:

    在 XML 文件中,当我们添加一个元素并为其设置属性时,我们只 设置这些属性的值,现在对于每个元素,都有一个类来绘制它 在屏幕上,此类具有与 XML 文件中的属性名称相同的属性 现在使用文件的读写算法,这些 XML 文件中的值被传输到元素的 java 文件(类),然后类在屏幕上绘制该元素。

    在元素的类绘制它之前,有一个所有元素的超类,所有元素的父类称为View(活动中的每个元素都称为视图)该类具有所有元素的基本属性和此类是 XML 文件中的属性将被传输给它的类。

    方法findViewById()返回一个View类型的对象,这个对象保存了属性值,然后我们需要将它强制转换为特定的元素,例如TextView是一个类来绘制文本视图这个类和所有元素' classes 是 View 类的子类,所以我们要做的是向下转换,当这个方法返回 View 类型的对象时,我们将它向下转换为元素类

    它如何找到属性?如果 XML 文件中的标记首先在 XML 文件中搜索包含元素名称的标记,则它使用 id 查找元素的属性,然后如果它是它想要的 id,它会查看 id 然后它会接受它,否则它会搜索另一个标签(具有相同的元素名称)。

    我们通过这种方法给它 id。有一个类叫做 R(resources),这个类有嵌套类(id、string、colors)这些类具有相同类型的属性并保存特定值,例如,id 类它具有存储每个 id 的属性XML 文件中的每个元素,所以当我们想为方法 findViewById() 提供 id 时,我们会转到这个类并告诉它进入 id 类并选择我们想要的元素的 id。

    ِِ 然后进入 XML 文件并查找具有此 id 的元素并获取属性并将它们传递给类视图对象,当它返回对象时,我们将其向下转换为元素的类我们想画它 并处理它。

    【讨论】:

      【解决方案2】:

      Activity 中的根视图由setContentView(int layoutId)setContentView(View rootView) 确定。

      在你的情况下,它是

      setContentView(R.layout.activity_main);
      

      因此,您对findViewById 的任何调用都会从activity_main.xml 查找ID。

      如果找不到你指定的id,则返回null。


      值得一提的是,您没有调用该方法,这通常是制作 Toast 的方式。

      Toast.makeText(getApplicationContext(), "Hello toast!", Toast.LENGTH_SHORT).show();
      

      【讨论】:

      • “因此,您对 findViewById 的任何调用都会从 activity_main.xml 中查找 id。” --- 但我正在搜索的 Id 在 toast.xml 中并且可以正常工作。
      • 在您显示的代码中,findViewById is 在 activity_main 上调用,因为您是从 Activity 类调用它(例如 this.findViewById)。如果你想在 toast 布局上调用它,那么你需要做v.findViewById。如果它以当前方式工作,那么我想您已经在两个 XML 文件中复制了 R.id
      • 所以你的问题是它没有显示任何东西?请参阅我的答案,如果找不到 ID,它将返回 null 吗?这正是正在发生的事情,因为您发现视图布局错误
      • 它可以正常工作。我的意思是,如果从 R.layout.toast 膨胀的视图被设置为活动的根视图的子视图(如@Grestmann 所说),为什么它不会在膨胀后立即显示。但是当调用 toast 的 show 方法时它会显示出来。因此,从 R.layout.toast 膨胀的视图被设置为活动根视图的子级的说法似乎是错误的。
      【解决方案3】:

      Activity 的情况下,findViewById 从活动的内容视图(使用setContentView 设置)开始搜索,活动是从布局资源扩展的视图层次结构。

      【讨论】:

      • 所以从R.layout.toast 膨胀的View 被设置为内容视图的子项?如果是,那为什么它一充气就没有出现?
      • @cricket_007 我在单击按钮时调用该方法。我要说的是,如果从R.layout.toast 膨胀的View 被设置为活动的根View 的子节点,为什么它一旦膨胀就不会出现?我尝试在充气视图上设置.setVisibility(View.VISIBLE)
      • @q126y 检查膨胀视图和父视图(R.id.toastViewGroup)的布局参数(宽度、高度)。可能是它不知道如何计算它的大小。
      • @Gerstmann 他们知道如何计算他们的大小。这是布局文件pastebin.com/QLbbLUdL
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-24
      • 2016-11-13
      相关资源
      最近更新 更多