使用循环删除某些布局视图

时间:2018-12-31 07:45:35

标签: java android loops layout

我正在使用添加到布局中的方法动态创建视图。 我正在尝试实现另一个按钮,该按钮应该访问布局并通过使用循环将其删除,但是我的应用似乎一直崩溃。  我尝试使用循环来完成此操作,因为我不想通过方法removeAllViews()removeAllViewsInLayout()删除所有视图。

public void RemoveViews() {

    ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.constraintId);

    // I'd like to keep a text view and a button, but remove the rest.

    TextView textView1 = (TextView) findViewById(R.id.textView1);
    int textView1Id = textView1.getId();
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    int fabId = fab.getId();

    int count = layout.getChildCount();

    for(int i=0;i<count;i++) {
        View childPos = layout.getChildAt(i);
        int childId = layout.getChildAt(i).getId();

        // Here I try to detect whether the child is the text view or button.

        if(textView1Id == childId || fabId == childId) {}
        else {
            // The line below causes the crashing.
            layout.removeView(childPos);

            // This one also crashes:
            //layout.removeViewAt(i);
        }
    }
}

这是activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
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:id="@+id/constraintId"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
    android:id="@+id/textView1"
    android:onClick="onClick_textView1"
    android:padding="20dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="40dp"
    android:gravity="center"
    android:text="@string/text1"
    android:textColor="#808080"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    android:layout_marginEnd="16dp"
    android:layout_marginBottom="16dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:srcCompat="@drawable/ic_refresh_black_24dp" />

</android.support.constraint.ConstraintLayout>

我认为这是错误的日志(致命异常:主要):

2018-12-31 14:57:33.004 7507-7507/com.example.test4 E/AndroidRuntime: FATAL 
EXCEPTION: main
Process: com.example.test4, PID: 7507
java.lang.IllegalStateException: Could not execute method for android:onClick
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
    at android.view.View.performClick(View.java:6294)
    at android.view.View$PerformClick.run(View.java:24774)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:172)
    at android.app.ActivityThread.main(ActivityThread.java:6590)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
    at android.view.View.performClick(View.java:6294) 
    at android.view.View$PerformClick.run(View.java:24774) 
    at android.os.Handler.handleCallback(Handler.java:790) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:172) 
    at android.app.ActivityThread.main(ActivityThread.java:6590) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getId()' on a null object reference
    at com.example.test4.MainActivity.RemoveKeyboardList(MainActivity.java:115)
    at com.example.test4.MainActivity.onClick_textView1(MainActivity.java:64)
    at java.lang.reflect.Method.invoke(Native Method) 
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
    at android.view.View.performClick(View.java:6294) 
    at android.view.View$PerformClick.run(View.java:24774) 
    at android.os.Handler.handleCallback(Handler.java:790) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:172) 
    at android.app.ActivityThread.main(ActivityThread.java:6590) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

基本上,我想知道如何在不使应用程序崩溃的情况下执行此操作,以及是否有更好的方法从布局中删除多个视图。

//

解决方案

由于Anmol的建议,可以将动态创建的视图添加到单独的布局中,尽管我无法使其与循环配合使用,但我实现了我所需要的。我在这里包括了我的解决方案,因为与他的有些不同,尽管我接受了他的回答。抱歉,是一样的,但是我已经包括了如何实现它的所有步骤。请在到期时注明信用额。

步骤1: 添加另一种布局以包含在activity_main.xml中。我将其命名为dynamic_content.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
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:id="@+id/dynamic_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

</android.support.constraint.ConstraintLayout>

第2步:activity_main.xml中包括新布局。

// Add the line below anywhere as far as I know.
<include layout="@layout/dynamic_content" />

步骤3:仅将所有动态创建的视图包括在新布局中。

ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.dynamic_content);

// Create new text views, buttons, etc.
layout.addView(newTextView);

步骤4:创建删除它们的功能。

public void RemoveViews() {
    ConstraintLayout dynamic = (ConstraintLayout) findViewById(R.id.dynamic_content);
    dynamic.removeAllViews();
}

步骤5:将功能添加到按钮。

public void onClick_buttonName(View v)
{
    RemoveViews();
}

完成-尽情享受吧!

4 个答案:

答案 0 :(得分:3)

根据您的用例,您可以在布局中添加containerLayout并将所有动态视图添加到该容器中,而当您要删除动态视图时,只需执行以下操作即可。

public void AddViewToContainer(View view){

    ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.containerfordynamic_view);

    layout.addView(view);

}

public void RemoveViews() {

    ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.containerfordynamic_view);

    layout.removeAllViews();

}

第二个选项是在布局上执行removeAllView()并再次添加editText和Fab按钮,

但这不是首选,因为当前您仅保留两个View,但是如果列表增加,那么对于简单操作而言,这将增加过多的开销,因此最好选择第一个易于管理和操作的解决方案。

谢谢。

答案 1 :(得分:0)

视图具有“可见”,“消失”,“不可见”三种状态。 请设置视图状态为GONE,它将被清除掉内存,但是如果您只是想隐藏视图,只需将其设置为不可见即可。...

答案 2 :(得分:0)

您可以将容器布置为ViewGroup并循环浏览:

ViewGroup viewGroup = (LinearLayout) findViewById(R.id.layout);

for(int index=0; index<((ViewGroup)viewGroup).getChildCount(); ++index) {
    View nextChild = ((ViewGroup)viewGroup).getChildAt(index);
    nextChild.setVisibility(View.GONE); // This will somehow remove the view from Ui
    viewGroup.removeView(nextChild); // Or really remove it to be wiped out of memory
}

答案 3 :(得分:0)

您会收到NullPointerException,因为您尝试访问不再存在的视图。删除视图时,ConstraintLayout中的视图少了一个,但是count变量保持不变。

因此,您必须在循环迭代中计算视图数。

您每次删除视图时都会减少i,因为在删除视图时,所有视图都将向后移动一个元素。

for(int i = 0; i < layout.getChildCount(); i++) {
    if(textView1Id == childId || fabId == childId) {}
    else {
        layout.removeView(childPos);
        i--;
    }
}