视图未正确包含在单个列表项中

时间:2017-07-29 22:21:07

标签: java android android-layout listview

我的目标是从适配器中提取三个JSON Objects并在一个list item中将它们显示为三个文本视图。当目前只有一组对象时,它应该看起来像这样: enter image description here

相反它显示了这个:

enter image description here

我在XML或适配器中看不到任何错误。 (如下所示)可能导致文本视图拆分成比这更需要的列表项的原因是什么?

list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:padding="2dp"
    android:layout_height="match_parent">


    <RelativeLayout
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:id="@+id/outer"
        android:padding="3dp"
        android:background="#08445e"
        android:layout_toLeftOf="@+id/button"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <TextView
            android:id="@+id/textViewRoom"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Room "
            android:textColor="#fff"
            android:layout_alignParentLeft="true"/>

        <TextView
            android:id="@+id/textViewTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Time: "
            android:layout_alignParentRight="true"
            android:textColor="#fff" />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/inner"
        android:background="#d1d1d1"
        android:layout_below="@+id/outer"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_toLeftOf="@+id/button"
        android:layout_toStartOf="@+id/button">

        <TextView
            android:id="@+id/textViewRequest"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:textColor="#000"
            android:textSize="20sp"
            android:layout_centerHorizontal="true" />

    </RelativeLayout>

    <Button
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="#dc2f2f"
        android:id="@+id/button"
        android:text="Mark Done"
        android:textColor="#fff"
        android:textAllCaps="false"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignBottom="@+id/inner"
        android:layout_alignParentTop="true" />
</RelativeLayout>

MainAdapter.Java:

package com.example.duncan.recyclerviewproject;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;



public class MainAdapter extends BaseAdapter {
    SharedPreferences preferences;

    Context context;
    ArrayList<String> arraylist=new ArrayList<>();

    public MainAdapter(Context context,
                       ArrayList<String>arrayList){
        this.context=context;
        this.arraylist=arrayList;
    }


    @Override
    public int getCount() {
        return arraylist.size();
    }

    @Override
    public Object getItem(int i) {
        return i;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    public class ViewHolder{
        Button   mark_btn;
        public TextView textViewRoom;
        public TextView textViewRequest;
        public TextView textViewTime;
    }

    @Override
    public View getView(final int position, View row, ViewGroup parent) {
        View convertView=row;
       final ViewHolder holder;
        if(convertView==null) {

            holder=new ViewHolder();
            LayoutInflater infalInflater = (LayoutInflater)
                    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.custom_layout, null);

            holder.mark_btn= (Button) convertView.findViewById(R.id.button);
            holder.textViewRoom = (TextView) 
convertView.findViewById(R.id.textViewRoom);
            holder.textViewRequest = (TextView) 
convertView.findViewById(R.id.textViewRequest);
            holder.textViewTime = (TextView) 
convertView.findViewById(R.id.textViewTime);
            convertView.setTag(holder);

        }else{
            holder = (ViewHolder) convertView.getTag();

        }


        holder.textViewRoom.setText(arraylist.get(position));
        holder.textViewRequest.setText(arraylist.get(position));
        holder.textViewTime.setText(arraylist.get(position));

        holder.mark_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Marked complete", 
Toast.LENGTH_SHORT).show();
            }
        });


        return convertView;
    }

    }

MainActivity.java

package com.example.duncan.recyclerviewproject;

import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import me.anwarshahriar.calligrapher.Calligrapher;

public class MainActivity extends AppCompatActivity {


    private static final String URL_DATA = 
"https://summerproject17.herokuapp.com/api/request/?format=json";
    private ListView recyclerView;
    private MainAdapter adapter;

    private ArrayList<String> listItems;

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

        recyclerView = (ListView) findViewById(R.id.list);
       /* recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));*/
//is the below line newly added?
        listItems = new ArrayList<>();

        loadRecyclerViewData();

        Calligrapher calligrapher = new Calligrapher(this);
        calligrapher.setFont(this, "elegantluxpro-mager.ttf", true);

    }


    private void loadRecyclerViewData(){
        StringRequest stringRequest = new StringRequest(Request.Method.GET,
                URL_DATA,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                            JSONObject jsonObject = new JSONObject(response);
                            JSONArray array = 
jsonObject.getJSONArray("results");

                            for(int i = 0; i < array.length(); i++){
                                JSONObject o = array.getJSONObject(i);
                              /*  ListItem item = new ListItem(
                                        o.getString("room"),
                                        o.getString("request"),
                                        o.getString("unixTime")
                                );*/
                                listItems.add(o.getString("room"));
                                listItems.add(o.getString("request"));
                                listItems.add(o.getString("room"));
                            }

                            Log.e("size",""+listItems.size());

                            adapter = new 
MainAdapter(MainActivity.this,listItems);
                            recyclerView.setAdapter((ListAdapter) adapter);

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("VOLLEY", error.getMessage());
                    }
                });
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    }
}

activity_main.xml列表视图部分:

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/list"
    android:layout_below="@+id/relativeLayout2">

</ListView>

注意:我在一周左右的时间里问了一个类似的问题,但不同之处在于列表项的结构已经改变,并且在这个问题中提供了更多细节。

2 个答案:

答案 0 :(得分:2)

  

我的目标是从适配器中提取3个JSON对象,并在一个列表项中将它们显示为3个文本视图。当现在只有一组对象时,它应该看起来像这样:

列表适配器设计为具有1到1的映射,其中包含支持它的列表。因此,根据我的理解,您的上述方法存在一些缺陷。如果您希望将三个JSON对象显示为单个列表项的三个TextView,则需要转换为另一个由(例如)类{{1}组成的列表你定义的。为此使用自定义适配器查找ViewHolder。不确定ListView为什么是内部类,它可以只是同一文件中的非公共类。

  

我在XML中看不到任何错误

您的xml布局中似乎存在一些冗余。你可以做的是为你的列表项定义一个自定义布局,它有一个ViewHolder,它包含所有三个文本视图和按钮(类似这样)。

RelativeLayout

或者您可以使用<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/list_item" android:padding="3dp"> <TextView android:id="@+id/textViewRoom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Room " android:textColor="#fff" android:layout_alignParentTop="true" android:layout_alignParentLeft="true"/> <Button android:layout_width="60dp" android:layout_height="60dp" android:background="#dc2f2f" android:id="@+id/button" android:text="Mark Done" android:textColor="#fff" android:layout_alignParentRight="true" android:layout_alignParentTop="true" /> <TextView android:id="@+id/textViewTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Time: " android:layout_alignParentTop="true" android:alignLeft="@id/button" android:textColor="#fff" /> <TextView android:id="@+id/textViewRequest" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:textColor="#000" android:textSize="20sp" android:alignBottom="@id/textViewRoom" android:alignLeft="@id/button" android:layout_centerHorizontal="true" /> </RelativeLayout> LinearLayout的组合。但是RelativeLayout中没有方向属性,所以你也需要摆脱它。

不确定这是否足以解决您正在努力解决的具体问题,但我希望它有所帮助。

答案 1 :(得分:2)

正如adamarta所说,你的列表和列表之间存在1比1的映射关系。显示了什么。 ArrayList中的1个项目在ListView中为您提供了1个项目。执行此操作的常用方法是创建数据模型类。它看起来像这样。

public class RoomItem {
    private String room;
    private String time;
    private String request;

    public RoomItem(String room, String request, String time) {
        this.room = room;
        this.request = request;
        this.time = time;
    }

    public RoomItem() {        
    }

    public String getRoom() {
        return room;
    }

    public void setRoom(String room) {
        this.room = room;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getRequest() {
        return request;
    }

    public void setRequest(String request) {
        this.request = request;
    }
}

您的ArrayList声明会发生这样的变化。

    private ArrayList<RoomItem> listItems;

您还必须更改适配器中的ArrayList用途。

此外,在适配器的getView()中,设置如下的值

    holder.textViewRoom.setText(arraylist.get(position).getRoom());
    holder.textViewRequest.setText(arraylist.get(position).getRequest());
    holder.textViewTime.setText(arraylist.get(position).getTime());

在MainActivity中,在loadRecyclerViewData()中,用此替换您当前的3个listItems.add(...)

    // create a new data item with the new information
    RoomItem item = new RoomItem(o.getString("room"),
            o.getString("request"),
            o.getString("room"));)

    // then add that item to the list 
    listItems.add(item);

你也可以创建一个空项目然后添加每个字段(做这个或上面的代码,而不是两个)

    RoomItem item = new RoomItem();
    item.setRoom(o.getString("room");
    etc.

至于你的布局,如果它在预览中看起来没问题,那么它可能没问题。除了... 您正在用值替换标签(房间和时间)。我不认为你想这样做。我认为这就是你所需要的。

    <TextView
        android:id="@+id/textViewRoomLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Room: "
        android:textColor="#fff"
        android:layout_alignParentLeft="true"/>

    <TextView
        android:id="@+id/textViewRoom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="placeholder"
        android:textColor="#fff"
        android:layout_toEndOf="@+id/textViewRoomLabel"
        android:layout_marginStart="10dp"
        />

    <TextView
        android:id="@+id/textViewTimeLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Time: "
        android:layout_toStartOf="@+id/textViewTime"
        android:layout_marginEnd="10dp"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/textViewTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="placeholder"
        android:layout_alignParentRight="true"
        android:textColor="#fff" />

我还没有构建并对其进行测试,所以我可能错过了一些小问题,例如需要对新ArrayList等进行更改,但我认为这就是您所需要的。