简体   繁体   中英

How can I fix the layout views in my android app?

I'm trying to create the buttons using my api. I make a call to the api using the Retrofit and then I create the buttons. But there is a code error! The data returned in the API response is correct but creating the views is a problem.

It says that I need to removeView() . I did that but there is no data printing now.

My code:

package com.example.englishapp;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


public class LessonsActivity extends AppCompatActivity {

    private TextView textViewResult;
    String URL = "http://kurchanovenglish.ru/data/";

    private String[] name = new String[18];



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lessons);


        final LinearLayout layout = new LinearLayout(this);

        final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT
        );
        params.setMargins(250, 10, 250, 50);
        layout.setOrientation(LinearLayout.VERTICAL);
        int i;

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);

        Call<List<Lesson>> call = jsonPlaceHolderApi.getPosts();


        final LinearLayout row = new LinearLayout(this);
        final Button button = new Button(this);
        call.enqueue(new Callback<List<Lesson>>() {


            @Override
            public void onResponse(Call<List<Lesson>> call, Response<List<Lesson>> response) {


                if (!response.isSuccessful()) {
                    textViewResult.setText("Code: " + response.code());
                    return;
                }

                List<Lesson> lessons = response.body();

                int b = 0;

                String[] name = new String[18];

                for (Lesson lesson : lessons) {

                    button.setText(lesson.getName());
                    button.setId(lesson.getNumber());
                    button.setLayoutParams(params);
                    button.setTextSize(20);
                    /*button.setBackground(this.getResources().getDrawable(R.drawable.buttons));*/
                    button.setOnClickListener(new View.OnClickListener() {
                        @SuppressLint("ShowToast")
                        @Override
                        public void onClick(View v) {
                            Intent intent = new Intent(LessonsActivity.this, WelcomeActivity.class);
                            startActivity(intent);
                        }
                    });
                    row.removeView(layout);
                    row.addView(button);
                }
                layout.addView(row);


                }


            @Override
            public void onFailure(Call<List<Lesson>> call, Throwable t) {
                textViewResult.setText(t.getMessage());
            }
        });


    }
}

The error:

/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.englishapp, PID: 19385
    java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
        at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
        at android.view.ViewGroup.addView(ViewGroup.java:4746)
        at android.view.ViewGroup.addView(ViewGroup.java:4686)
        at android.view.ViewGroup.addView(ViewGroup.java:4659)
        at com.example.englishapp.LessonsActivity$1.onResponse(LessonsActivity.java:92)
        at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$1.run(DefaultCallAdapterFactory.java:83)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Help me please. I don't know what to do.

Here is what you're doing wrong; You are using the same Button instance and adding it again to row ( LinearLayout ).

If I understand correctly this is the view hierarchy you want.

LinearLayout

    --LinearLayout

        --Button

        --Button

        .

    --LinearLayout

        --Button

        --Button

        .
.

First thing you need to understand is that you cannot reuse a View in multiple places in the view hierarchy. Secondly a View cannot be a child to multiple parents ie a same Button cannot be present in two rows. Lets think about the reason for such restriction; say, you were allowed to add same Button to another parent, how would you then identify a click among them, how would you know which one you clicked. Furthermore say you have a text to display on one and a different one for the second Button , how would you change for each if/when you are sharing the reference. You see the problem?


However, since you are instantiating and adding the Button in Java code. You need to first create a new instance of Button to add to the parent row . Consequently you also need a new instance of row to add to the parent layout if you are adding more than one rows.

Your code then becomes:

for (Lesson lesson : lessons) {

    Button button = new Button(LessonsActivity.this);
    button.setText(lesson.getName());
    button.setId(lesson.getNumber());
    button.setLayoutParams(params);
    button.setTextSize(20);
    /*button.setBackground(this.getResources().getDrawable(R.drawable.buttons));*/
    button.setOnClickListener(new View.OnClickListener() {
    @SuppressLint("ShowToast")
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(LessonsActivity.this, WelcomeActivity.class);
            startActivity(intent);
            }
        });

        row.addView(button);
    }
    layout.addView(row);
}

You will need to adjust layout.addView(row); accordingly but same principle follows.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM