以编程方式将 TextView 设置为 RelativeLayout.CENTER_OF_PARENT

Posted

技术标签:

【中文标题】以编程方式将 TextView 设置为 RelativeLayout.CENTER_OF_PARENT【英文标题】:Programmatically setting TextView to RelativeLayout.CENTER_OF_PARENT 【发布时间】:2018-02-02 22:08:28 【问题描述】:

我刚刚学习 Java 和 XML,并试图将 TextView 设置为位于其父级 RelativeLayout 的中心。仅当我注释掉 setContentView(homeScreen) 之前的最后 3 行时,我的应用才会加载

这是我的 XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context=".MainActivity">

</RelativeLayout>

这是我的 Java:

package com.example.android.testerapp1;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity 

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);


    TextView homeScreen = new TextView(this);
    homeScreen.setText("Welcome to Test App 001" + "\nThis TextView was created dynamically in Java!");
    homeScreen.setTextSize(24);
    homeScreen.setTextColor(Color.CYAN);
    homeScreen.setCursorVisible(true);
    homeScreen.setPadding(16,56,16,56);
    homeScreen.setBackgroundColor(Color.BLACK);
    homeScreen.setGravity(Gravity.CENTER);

    //dynamically set width to dp (converted to pixels ~600) and height to 'wrap content'
    // convert dp amount to pixels for size
    final float scale = getResources().getDisplayMetrics().density;
    int pixelWidth = (int) (2000 / scale + 0.5f);

    homeScreen.setLayoutParams(new ViewGroup.LayoutParams(pixelWidth , ViewGroup.LayoutParams.WRAP_CONTENT));

    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)homeScreen.getLayoutParams();
    params.addRule(RelativeLayout.CENTER_IN_PARENT);
    homeScreen.setLayoutParams(params);


    setContentView(homeScreen);
    

我已经看过这种帖子大约 10 次了,他们都有相同的解决方案,但我似乎无法正确实施,这可能是我代码的另一部分?可能我在哪里使用setLayoutParamsalso 设置宽度和高度?

【问题讨论】:

【参考方案1】:

setContentView() 调用应该用于设置全屏的布局。您当前在 Activity 代码中所做的只是将 TextView 设置为屏幕的完整视图,因此 Activity 没有对您创建的 XML 布局的引用。这就是你最后的 3 行代码失败的原因,因为 TextView 正在尝试设置其 LayoutParams 以了解其父级应如何放置和测量它,但是在这种情况下它没有父级。我建议做的是给 XML 中的 RelativeLayout 一个 id 属性,以便在 Activity 代码中获得对它的引用,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="home_screen_layout"
android:layout_
android:layout_
tools:context=".MainActivity"/>

然后在您的Activity 代码中进行调整,以便您使用 XML 文件的资源 ID 进行调用。如果我们假设它在资源目录的布局文件夹中被称为act_main.xml(即在src/main/resources/layout/act_main.xml 中),那么您将在super() 调用之后调用setContentView(R.layout.act_main) 作为onCreate() 中的第一行,以便框架具有有机会解析您的 XML 并将其膨胀(即实例化、计算大小和 确定其组件的位置等)。之后,使用findViewById(R.id.home_screen_layout) 获取对该RelativeLayout 的引用,以便您可以创建一个新的TextView 并将其添加到您已经膨胀的布局中。

package com.example.android.testerapp1;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity 

    // make your view components private members as findViewById calls are expensive for the framework
    private RelativeLayout homeScreenLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        // Have the activity inflate the XML file with your RelativeLayout
        setContentView(R.layout.act_main);

        // Now that it is inflated, get a reference to that parent
        homeScreenLayout = (RelativeLayout) findViewById(R.id.home_screen_layout);

        // Dynamically create a TextView associated with this Activity's context
        TextView homeScreen = new TextView(this);
        homeScreen.setText("Welcome to Test App 001" + "\nThis TextView was created dynamically in Java!");
        homeScreen.setTextSize(24);
        homeScreen.setTextColor(Color.CYAN);
        homeScreen.setCursorVisible(true);
        homeScreen.setPadding(16,56,16,56);
        homeScreen.setBackgroundColor(Color.BLACK);
        homeScreen.setGravity(Gravity.CENTER);

        //dynamically set width to dp (converted to pixels ~600) and height to 'wrap content'
        // convert dp amount to pixels for size
        final float scale = getResources().getDisplayMetrics().density;
        int pixelWidth = (int) (2000 / scale + 0.5f);

        // Adjust the placement in the parent
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(pixelWidth , RelativeLayout.LayoutParams.WRAP_CONTENT)    
        params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); // make sure to use the function which takes a boolean value for rules like CENTER_IN_PARENT
        homeScreen.setLayoutParams(params); // Add these parameters to the textview

        // Let the layout know about your newly created textview so that it can re-draw its canvas
        homeScreenLayout.addView(homeScreen);

    

作为说明,我将补充一点,您正在做的事情可以相对容易地在 XML 中完成,但是由于您询问了有关以编程方式具体设置它的问题,因此我不会详细介绍这方面的内容。但如果您对某些结构化资源感兴趣,我建议您查看Android Developer Guide,特别是XML layouts and how they interact with Activities 部分

编辑:注意我对活动代码所做的更改。主要部分首先使用setContentView(int id) 填充空的RelativeLayout xml,然后将另一个TextView 添加到给定的布局中。我提供的关于CENTER_IN_PARENT 行的代码中有一个小错误。根据 [docs](https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#addRule(int, int)),在添加使用布尔值的规则时,您必须使用函数的 addRule(int, int) 版本。

【讨论】:

这完全有道理,因为它没有父节点可以去中心。但是,我正在尝试在 Java 中动态创建 TextView 作为练习,因此您的回答只是部分有用。我想我需要先将TextView添加到RelativeLayout,然后将setContentView添加到RelativeLayout?我试过RelativeLayout homeLayout = (RelativeLayout)findViewById(R.id.homeLayout);,然后homeLayout.addView(homeScreen);,但即使更改为setContentView(homeLayout);.... 即使我不使用homeLayout.addView(homeScreen); 并完全忽略我的homeScreen,它仍然会崩溃。我相信问题出在RelativeLayout homeLayout = (RelativeLayout)findViewById(R.id.homeLayout); 然后setContentView(homeLayout); 应用程序甚至没有从我的预览窗口中显示“Hello World”,它只是变黑并关闭。有没有办法在java中将homeScreen添加到RelativeLayout并仍然调用setContentView(R.layout.activity_main) 好吧,我会说,如果您想以编程方式创建所有布局组件,包括您的RelativeLayout,那么您将实例化所有视图并将RelativeLayout 传递给正确的setContentView(View view, ViewGroup.LayoutParams param) 调用(注意here 中记录的函数参数)。由于您只想动态添加 TextView,因此您调用 setContentView(int id) 然后使用 findViewById()RelativeLayout【参考方案2】:

可以在构造函数上设置宽高,然后使用

Relative.LayoutParams(int width, int height)

所以你需要这样做:

homeScreen.setLayoutParams(width , height);

【讨论】:

不幸的是,我收到一个错误,即我没有将两个 'int' 传递给 'setLayoutParams' 方法 - 我最初尝试了您的方法,但在研究了 ***.com/questions/9678785/… 和 ***.com/questions/4854492/…

以上是关于以编程方式将 TextView 设置为 RelativeLayout.CENTER_OF_PARENT的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式设置 TextView 的布局权重

如何将setOnClickListener设置为以编程方式添加的TextView?

以编程方式设置TextView的布局权重

以编程方式在android中将下划线文本设置为TextView

以编程方式设置 TextView 的样式

以编程方式在 TextView 中设置文本对齐方式