在同一个TableRow中查找元素

时间:2018-05-09 09:09:43

标签: android

我正在尝试创建一个功能,将当前分散在项目不同部分的信息整合在一起。

作为此任务的一部分,我有一个布局文件,其中包含以下内容...基本上是一组行,每行都有一个标签(TextView)和一个UI元素(例如{{ 1}},CheckBoxSpinner)来收集用户的信息:

EditText

我已经拥有了UI元素的所有<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/MyLinearLayout.Section" android:id="@+id/section_pressure" > <TableLayout style="@style/MyTableLayout" android:id="@+id/table_pressure" > <TableRow style="@style/MyTableRow" > <TextView style="@style/MyTextView.Label.WithHelp" android:tag="label_show" android:text="@string/label_show" /> <CheckBox style="@style/MyCheckBox" android:id="@+id/pressure" /> </TableRow> <TableRow style="@style/MyTableRow" > <TextView style="@style/MyTextView.Label.WithHelp" android:tag="label_unit" android:text="@string/label_unit" /> <Spinner style="@style/MySpinnerStyle" android:id="@+id/pressureUnit" /> </TableRow> </TableLayout> </LinearLayout> 值的数组,并且我想要生成相应android:id标签的另一个数组。

e.g。来自android:text我希望从R.id.pressureUnit找到关联的R.string.label_unit,以便我有一个关于每个UI元素使用什么标签的中央记录...目前该信息分散在许多不同的布局文件。

这可以通过编程方式实现吗?

3 个答案:

答案 0 :(得分:3)

根据我的理解,您希望找到给定视图的兄弟视图的@string资源ID。

假设您的xml文件已经膨胀,您可以执行以下操作:

private int getSiblingStringId(@IdRes int viewId) {
    View uiElement = findViewById(viewId);
    ViewGroup parent = (ViewGroup) uiElement.getParent();

    // iterate through the siblings
    for (int i = 0; i < parent.getChildCount(); i++) {
        View view = parent.getChildAt(i);
        if (view instanceof TextView) {
            String value = ((TextView) view).getText().toString();

            // found
            return getStringIdFromValue(value);
        }
    }

    throw new IllegalArgumentException("no TextView sibling for " + viewId);
}

private int getStringIdFromValue(String value) {
    // get all fields using reflection
    Field[] fields = R.string.class.getDeclaredFields();

    for (Field field : fields) {
        int stringResId = getResources().getIdentifier(field.getName(), "string", getPackageName());
        String s = getString(stringResId);
        if (s.equals(value)) return stringResId;
    }

    throw new IllegalArgumentException("no matching string for " + value);
}

以上代码适用于活动。您可能需要为其他类稍微修改一下。 (您需要致电findViewByIdgetResourcesgetString

答案 1 :(得分:0)

好吧,我会为每个表格行设置一个ID。然后,通过迭代行的子项,以编程方式获取每行下的每个子视图。从那里,您可以通过使用instanceof简单地确定您所在的位置来轻松操纵每个视图。但是,让我们假设你不能改变它,你仍然可以这样做,但它可能效率不高。

由于我不知道你的id数组的结构,我只假设它是一个名为uiIds的整数数组。然后,你必须做类似

的事情
TableLayout layout = findViewById(R.id.table_pressure);
TableRow tr = null;
View rowChild = null;
TextView tv = null;
View secondaryView = null;

int tableChildCount = layout.getChildCount();
int rowChildCount = 0;

// Since I don't really know the structure of your array of ids,
// I just assume its an array of integers called uiIds

//This will contain the corresponding text strings of every textview
List<String> textLabels = Arrays.asList(new String[uiIds.length]);

// Go over all the rows on your table
for (int i = 0; i < tableChildCount; i++) {
    // I'm assuming that you only have rows as the children of your table
    tr = (TableRow) layout.getChildAt(i); //This is the row

    rowChildCount = tr.getChildCount();
    tv = null;
    secondaryView = null;

    // Now go over all the children of the current row i
    for (int j = 0; j < rowChildCount; j++) {
        // Here I'm also assuming you only have two children on every row
        rowChild = getChildAt(j);
        // At this point, the view v could be any type of the ones you have
        // used. Since we are interested in TextView simply do an instanceof
        if ( rowChild  instanceof TextView ) {
            tv = (TextView) v;
        } else {
            // This is the other view in the row. The ones from which you alreade have its ids
            // e.g. the spinner with id pressureUnit
            secondaryView = rowChild; //We do not need to cast
        }
    }

    // Now we construct the array        
    if (tv != null && secondaryView != null) {
        // The id we just obtained is one from the ones you have already saved
        // in an array called uiIds
        int secondaryViewId = secondaryView.getId();

        //Now, we need to find the index of this id in uiIds
        for (int idx = 0; idx < uiIds.length; idx++) {
            if ( uiIds[idx] == secondaryViewId ) {
                //We have found a match. Then just add the text of the  textview in the corresponding index of our new array
                textLabels.set(idx,tv.getText().toString());
            }
        }

    }

}

// At this point, textLabels should contain the text of the text view on every row
// such that the ith element in the array you already have corresponds to 
// ith element of the array we just created. 
// In other words, if uiIds[0] is equals to R.id.pressureUnit, then,
// textLabels.get(0) is equals to R.string.label_unit

我直接在文本编辑器上编辑了答案,因此它可能有一些sintax错误。希望这能解决您的问题,或至少给您一个想法。

答案 2 :(得分:0)

为了概述标签映射,我建议更系统地编码,在这种情况下,将标签命名为id。

  • > snappy@6.0.4 install /usr/src/app/node_modules/snappy > node-gyp rebuild make: Entering directory '/usr/src/app/node_modules/snappy/build' CXX(target) Release/obj.target/snappy/deps/snappy/snappy-1.1.7/snappy-sinksource.o CXX(target) Release/obj.target/snappy/deps/snappy/snappy-1.1.7/snappy-stubs-internal.o CXX(target) Release/obj.target/snappy/deps/snappy/snappy-1.1.7/snappy.o AR(target) Release/obj.target/deps/snappy/snappy.a COPY Release/snappy.a CXX(target) Release/obj.target/binding/src/binding.o In file included from ../src/./binding.h:3:0, from ../src/binding.cc:1: /root/.node-gyp/10.2.0/include/node/node.h:53:50: fatal error: core.h: No such file or directory #include "core.h" // NOLINT(build/include_order) ^ compilation terminated. make: Leaving directory '/usr/src/app/node_modules/snappy/build' make: *** [binding.target.mk:102: Release/obj.target/binding/src/binding.o] Error 1 gyp ERR! build error gyp ERR! stack Error: `make` failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node- gyp/lib/build.js:258:23) gyp ERR! stack at ChildProcess.emit (events.js:182:13) gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:237:12) gyp ERR! System Linux 4.9.87-linuxkit-aufs gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" gyp ERR! cwd /usr/src/app/node_modules/snappy gyp ERR! node -v v10.2.0 gyp ERR! node-gyp -v v3.6.2 gyp ERR! not ok =&gt; @+id/pressure
  • @string/label_pressure =&gt; @+id/pressureUnit

我知道这不是你问题的直接答案。但是我认为,如果你以这种方式工作,你根本不需要映射的中央表格,你的布局变得更具可读性。 Android Studio可以让您轻松进行此类更改。