Удалить определенные виды макета с помощью цикла - PullRequest
0 голосов
/ 31 декабря 2018

Я динамически создаю представления с помощью метода, который добавляю в свой макет.Я пытаюсь реализовать другую кнопку, которая должна получить доступ к макету и удалить их с помощью цикла, но мое приложение, похоже, постоянно падает.Я пытаюсь сделать это с помощью цикла, потому что я не хочу удалять все представления с помощью методов 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>

Я думаю, что это логкат ошибки (FATAL EXCEPTION: main):

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 голосов
/ 31 декабря 2018

В соответствии с вашим вариантом использования вы можете добавить 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,

Но это не должно быть предпочтительным, так как в настоящее время у вас есть только два вида для сохранения, но если список увеличивается, это слишком много дляпростое управление, поэтому лучше использовать первое решение, которым также легко управлять и которым можно манипулировать.

Спасибо.

0 голосов
/ 31 декабря 2018

Вы можете макетировать контейнер как 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
}
0 голосов
/ 31 декабря 2018

Вы получаете NullPointerException, потому что пытаетесь получить доступ к представлениям, которых больше не существует.Когда вы удаляете представление, у вас в представлении ConstraintLayout меньше одного представления, но ваша переменная count остается неизменной.

Таким образом, вам нужно вычислить количество представлений в итерации цикла.

И у вас есть декрементя каждый раз, когда вы удаляете вид, потому что когда вы удаляете вид, все виды после этого сдвигаются на один элемент назад.

for(int i = 0; i < layout.getChildCount(); i++) {
    if(textView1Id == childId || fabId == childId) {}
    else {
        layout.removeView(childPos);
        i--;
    }
}
0 голосов
/ 31 декабря 2018

Представления имеют три состояния: Видимый, УЖЕ, Невидимый .... Пожалуйста, установите для состояния просмотра УТВЕРЖДЕН, оно будет стерто из памяти, однако, если вы хотите просто скрыть представление, просто установите его невидимым ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...