简体   繁体   English

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

[英]Views not properly contained within single list item

My goal is to pull three JSON Objects from an adapter and display them as three text views in one list item . 我的目标是从适配器中提取三个JSON Objects ,并在一个list item中将它们显示为三个文本视图。 It should look like this when only one set of objects in present: 当前只有一组对象时应如下所示: 在此处输入图片说明

Instead it's showing this: 相反,它显示如下:

在此处输入图片说明

I can't see anything wrong in my XML or adapter. 我在XML或适配器中看不到任何错误。 (Shown Below) What can cause the textviews to split into more list items than desired like this? (如下所示)是什么导致文本视图像这样拆分成更多列表项的?

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: 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 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 list view portion: activity_main.xml列表视图部分:

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

</ListView>

Note: I asked a similar question a week or so back but this is different in that the structure of the list items has changed and more details have been provided in this question. 注意:我大约一周前问了一个类似的问题,但这是不同的,因为列表项的结构已更改,并且在此问题中提供了更多详细信息。

My goal is to pull 3 JSON Objects from an adapter and display them as 3 text views in one list item. 我的目标是从适配器中提取3个JSON对象,并在一个列表项中将它们显示为3个文本视图。 It should look like this when only one set of objects in present: 当前只有一组对象时应如下所示:

The list adapter is designed to have a 1 to 1 map with the list that is backing it. 列表适配器被设计为具有1:1映射以及支持它的列表。 Therefore your approach above is somewhat flawed as I understand it. 因此,据我了解,您的上述方法有些缺陷。 If you want three JSON Objects to be displayed as the three TextView s of a single list item , you need to translate to another List comprised of (for example) the class ViewHolder which you defined. 如果希望将三个JSON对象显示为单个列表项的三个TextView ,则需要转换为包含(例如)您定义的类ViewHolder另一个List。 Look up ListView using custom adapter for this. 为此,使用自定义适配器查找ListView Not sure why ViewHolder is an internal class, it can simply be a non-public class in the same file. 不确定ViewHolder为什么是内部类,它可以只是同一文件中的非公共类。

I can't see anything wrong in my XML 我在XML中看不到任何错误

There appear to be some redundancies in your xml layout. 您的xml布局中似乎有一些冗余。 What you could do is define a custom layout for your list item, which would have a single RelativeLayout that has all the three text views and the button (something like this). 您可以做的是为列表项定义一个自定义布局,该布局将具有一个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>

Or you could use a combination of LinearLayout and RelativeLayout . 或者,您可以结合使用LinearLayoutRelativeLayout But there is no orientation attribute in RelativeLayout , so you need to get rid of that as well. 但是RelativeLayout没有方向属性,因此您也需要摆脱它。

Not sure if this is sufficient to solve the specific problem you were struggling with but I hope it helps. 不知道这是否足以解决您所遇到的特定问题,但希望对您有所帮助。

As adamarta says, the there's a 1 to 1 mapping between your list & what's displayed. 正如adamarta所说,列表与显示内容之间存在一对一的映射关系。 1 item in your ArrayList gives you 1 item in your ListView. ArrayList中有1个项目,而ListView中有1个项目。 A common way of doing this is creating a data model class. 这样做的常见方法是创建数据模型类。 It would look like this. 看起来像这样。

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;
    }
}

Your ArrayList declaration would change like this. 您的ArrayList声明将像这样更改。

    private ArrayList<RoomItem> listItems;

And you'll have to change the ArrayList uses in your adapter as well. 而且,您还必须更改适配器中使用的ArrayList

Also, in getView() in the adapter, set the values like this 另外,在适配器的getView()中,设置如下所示的值

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

In MainActivity, in loadRecyclerViewData() , replace your 3 current listItems.add(...) with this. 在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);

You could also create an empty item then add each field (do either this or the above code, not both) 您还可以创建一个空项目,然后添加每个字段(执行此操作或执行上面的代码,而不要同时执行两个操作)

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

As for your layout, if it looks OK in the preview, then it's probably OK. 至于您的布局,如果在预览中看起来还可以,那么可能就可以了。 Except... you're replacing the labels (Room & Time) with the values. 除非...您要用值替换标签(“房间和时间”)。 I don't think you want to do that. 我想你不想那样做。 I think this is what you need. 我认为这就是您所需要的。

    <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" />

I haven't built and tested this so I may have missed a couple of small things like needing to make changes for the new ArrayList etc but I think this is what you need. 我还没有构建和测试它,所以我可能错过了一些小事情,例如需要为新的ArrayList进行更改等,但是我认为这是您所需要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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