【问题标题】:Creating layouts without an XML创建没有 XML 的布局
【发布时间】:2016-09-15 15:41:49
【问题描述】:

我读过布局 XML 文件被解释为 Java 代码,以这种方式构建视图层次结构。

首先,这是如何以及在哪里完成的?有人可以将我链接到进行这种解释的地方吗?

其次,是否可以不使用 XML 文件创建完整的布局?如果答案是肯定的,它是否有用? (它比 XML 文件有优势吗)大型应用程序会这样做吗?

【问题讨论】:

  • 只用java就可以制作图形了。
  • 是的,完全有可能。

标签: android


【解决方案1】:

我读过布局 XML 文件被解释为 Java 代码,以这种方式构建视图层次结构。

对于“解释为 Java 代码”这一短语的大多数定义并非如此。 XML 被解析并用于创建与 XML 中表达的视图相对应的 Java 对象。

有人可以将我链接到进行这种解释的地方吗?

You are looking for LayoutInflater,大概。

是否可以在不使用 XML 文件的情况下创建完整的布局?

当然。

它有什么用处吗?

对于琐碎的 UI(例如,整个内容视图是 WebView),它更简单一点,速度也快一点。

请注意,许多游戏将完全跳过基于 Java 的 UI,使用 OpenGL 从 C/C++ 渲染它们的输出。同样,混合应用程序框架(例如 PhoneGap)将跳过大部分基于 Java 的 UI 工作,因为它们通过 Web 技术(HTML、CSS、JS 等)呈现其 UI。

【讨论】:

  • 你的意思是有些安卓应用根本不使用Java?你指的是Android NDK吗?
  • @Pilpel:“你的意思是有些安卓应用根本不使用 Java?” ——他们没有写。框架提供了一些垫片(例如,NativeActivity)。 “你指的是Android NDK吗?” -- 对于 C/C++ 场景,是的。
【解决方案2】:

基本代码是这样的,我在我的博客上做了:

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // creating LinearLayout
        LinearLayout linLayout = new LinearLayout(this);
        // specifying vertical orientation
        linLayout.setOrientation(LinearLayout.VERTICAL);
        // creating LayoutParams  
        LayoutParams linLayoutParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 
        // set LinearLayout as a root element of the screen 
        setContentView(linLayout, linLayoutParam);

        LayoutParams lpView = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        TextView tv = new TextView(this);
        tv.setText("TextView");
        tv.setLayoutParams(lpView);
        linLayout.addView(tv);

        Button btn = new Button(this);
        btn.setText("Button");
        linLayout.addView(btn, lpView);


        LinearLayout.LayoutParams leftMarginParams = new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        leftMarginParams.leftMargin = 50;

        Button btn1 = new Button(this);
        btn1.setText("Button1");
        linLayout.addView(btn1, leftMarginParams);


        LinearLayout.LayoutParams rightGravityParams = new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        rightGravityParams.gravity = Gravity.RIGHT;

        Button btn2 = new Button(this);
        btn2.setText("Button2");
        linLayout.addView(btn2, rightGravityParams);
    }
}

【讨论】:

    【解决方案3】:
    • 是否可以在不使用 XML 文件的情况下创建完整的布局?

    当然可以。但是有用吗?如果您想以编程方式添加一些元素,则可能是这样。对于整个 UI,我认为由于 XML 创建的潜力而没有用处。

    示例:Adding LinearLayout programmatically in Android doesn't work

    LinearLayout LL = new LinearLayout(this);
    LL.setBackgroundColor(Color.CYAN);
    LL.setOrientation(LinearLayout.VERTICAL);
    
    LayoutParams LLParams = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
    
    LL.setWeightSum(6f);
    LL.setLayoutParams(LLParams);
    
    
    ImageView ladder = new ImageView(this);
    ladder.setImageResource(R.drawable.ic_launcher);
    
    FrameLayout.LayoutParams ladderParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);
    ladder.setLayoutParams(ladderParams);
    
    FrameLayout ladderFL = new FrameLayout(this);
    LinearLayout.LayoutParams ladderFLParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 0);
    ladderFLParams.weight = 5f;
    ladderFL.setLayoutParams(ladderFLParams);       
    ladderFL.setBackgroundColor(Color.GREEN);
    View dummyView = new View(this);
    
    LinearLayout.LayoutParams dummyParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,0);
    dummyParams.weight = 1f;
    dummyView.setLayoutParams(dummyParams);
    dummyView.setBackgroundColor(Color.RED);
    
    
    
    ladderFL.addView(ladder);
    LL.addView(ladderFL);
    LL.addView(dummyView);
    RelativeLayout rl=((RelativeLayout) findViewById(R.id.screenRL));
    rl.addView(LL);
    
    • 大型应用会这样做吗?

    一般用途的应用程序不这样做。但是有一些特定的情况对于以编程方式管理 UI 很有用。

    【讨论】:

      【解决方案4】:

      第一个问题

      XML 中的布局是 Java 对象的集合,例如:LinearLayout 解析为具有方法的 Java 类。当您调用findViewById 时,您将获得对该对象的引用,因此您可以调用该视图对象的不同方法。如果您对特定视图的工作原理感到好奇,您可以在类名上CMD + Click 并在 Android Studio 中获取反编译的源代码(Windows 的密钥会有所不同)。

      就 XML 如何知道要做什么而言,所有与android: 相关的标记都将由该视图的称为 AttributeSet 的类检索。从这里调用方法来执行相关的事情,例如设置文本大小或向类添加子视图。

      第二个问题

      是的,您可以在没有 XML 的情况下创建布局。您可以执行一些操作,例如从 LinearLayout 扩展为一个新类,然后在您的 ActivityonCreate 中,您可以将该视图传递给 setContentView,而不是布局参考。

      这有用吗?在大多数情况下并非如此,使用 XML 创建视图会更容易阅读和理解(是的图形预览)。但是,如果您需要创建自定义视图,那肯定是可以完成的,并且这样做有很多理由(例如扩展 ButtonLinearLayout 的功能)。

      你可以在Google's official documentation阅读更多关于视图的信息。

      【讨论】:

        【解决方案5】:

        已创建 Android XML 文件以简化布局创建。这些文件由 Java 代码解释并转换为对象。您可以创建自己的类(继承自 View、ViewGroups..)并使用自定义属性扩展 XML 布局。

        有时最好从 Java 代码生成视图,例如当应用程序需要根据数据模型呈现动态布局时。但在我看来,这不是一个好方法,使用 Java 创建所有布局(是的,总是可能的)。我能看到的唯一优势是避免了解析 XML 的时间,但这与布局代码组织无关。

        【讨论】:

          【解决方案6】:

          XML 文件被扩展为View 对象,是的。

          "这是如何以及在哪里完成的" -- 取决于您在代码中的位置。

          在活动中 - 你会看到 setContentView(View v)setContentView(int layoutRes)

          在片段中 - 您会看到 onCreateView 返回一个 View 对象。通常来自LayoutInflater

          是否可以在不使用 XML 文件的情况下创建完整的布局?

          当然。在某些情况下,您不需要编写自己的 XML 文件 - android.R.layout.* 有预定义的文件。例如,一个 ListView 和一个适配器。

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(android.R.layout.list_content); // Pre-defined ListView
              mListView = (ListView) findViewById(android.R.id.list); // Existing List ID
              mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1); // Item Layout
              mListView.setAdapter(mAdapter);
          

          但是,如果您的字面意思是不使用任何 XML 文件,那么您可以使用类似的东西 - 自己创建一个 View,然后在最后创建一个 setContentView

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
          
              LinearLayout ll = new LinearLayout(this);
          
              LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                      ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
              ll.setLayoutParams(lp);
          
              EditText editText = new EditText(this);
          
              Button b = new Button(this);
              b.setText("Click Me!");
              b.setOnClickListener(null);
          
              ll.addView(editText, 
                      new ViewGroup.LayoutParams(
                              ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
          
              ll.addView(b,
                      new ViewGroup.LayoutParams(
                              ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
          
              setContentView(ll);
          }
          

          如果答案是肯定的,它是否有用? (它比 XML 文件有优势吗)大型应用程序会这样做吗?

          我想不出它有用的理由。当然,您可以更好地控制动态视图,但是您无法使用布局编辑器轻松地可视化它们。

          我确信在某些情况下大型应用会这样做,但您是否计划构建需要大量重复使用自定义视图的大型应用?

          【讨论】:

          • 我想到了一个有用的理由,用代码而不是 XML 创建布局。如果你发布一个带有 XML 布局的库,它必须是 AAR 格式,这要求用户在使用它时在其依赖项中指定“@aar”,并要求用户在其依赖项中指定“{transitive = true}”如果您的库有依赖项。如果您想将库发布为不具备这些要求的 JAR 文件,则必须使用代码创建布局。
          【解决方案7】:

          现在可以使用 Jetpack compose 创建 android 声明式 UI,无需 xml

          https://developer.android.com/jetpack/compose

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-23
            • 1970-01-01
            • 2018-10-13
            • 1970-01-01
            • 2016-08-17
            • 1970-01-01
            相关资源
            最近更新 更多