Strange behavior of the RecyclerView - java

I have the following code for example.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> names = new ArrayList<>();
names.add("one");
names.add("two");
names.add("three");
names.add("four");
names.add("five");
names.add("six");
names.add("seven");
names.add("eight");
names.add("nine");
names.add("ten");
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(this);
rv.setLayoutManager(llm);
RvAdapter adapter = new RvAdapter(names);
rv.setAdapter(adapter);
}
}
RvAdapter.java
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.PersonViewHolder> {
public static final String TAG = RvAdapter.class.getSimpleName();
List<String> persons;
RvAdapter(List<String> persons) {
this.persons = persons;
}
#Override
public RvAdapter.PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new PersonViewHolder(v);
}
#Override
public void onBindViewHolder(RvAdapter.PersonViewHolder holder, int position) {
holder.name.setText(persons.get(position));
Log.d(TAG, "onBindViewHolder: " + position);
}
#Override
public int getItemCount() {
return persons.size();
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView name;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
name = (TextView) itemView.findViewById(R.id.name);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mrmayhem.myapplication.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<android.support.v7.widget.CardView
android:id="#+id/cv"
android:layout_width="match_parent"
android:layout_height="200dp">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.v7.widget.CardView>
</LinearLayout>
It works so good and correct. When I scroll through the list I get successive messages from Adapter one by one in Logs: "onBindViewHolder: " + position. But my problem in next. When i try add some View above the RecyclerView, as shown in the code below. Adapter displays all calls of the method onBindViewHolder simultaneously. Wrap the RecyclerView in activity_main.xml by the next code.
activity_main.xml (with header)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mrmayhem.myapplication.MainActivity">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HEADER" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>

RecyclerView is a ListView. It will only display the items that you can currently see, reusing parts as you scroll.
Now you wrap the RecyclerView in a LinearLayout within a NestedScrollView, what happens?
A NestedScrollView needs to know the size of the LinearLayout to handle the scrolling.
How does the LinearLayout know how long it should be, without knowing the RecyclerViews total length? It doesn't.
So the recyclerView gets completely inflated, all views at once, all in a long line. No recycling, no reuse. This is the phenomenon you experience.
Now the LinearLayout can properly tell the NestedScrollView it's height (the total height of the TextView and all the items of the RecyclerView) and the NestedScrollView can handle the scrolling.
This is why nested scrolling is always a bad idea. If possible, try to move your TextView as an item into the RecyclerView and get rid of the wrapping NestedScrollview.
e.g. as seen here: Is there an addHeaderView equivalent for RecyclerView?
Another option would be to remove the recyclerview from the scroll view and put it below. The header would not scroll then, though.

Unless you have a good reason to have a NestedScrollView in your hierarchy, you could achieve a TextView on top with a RecyclerView below with just this layout code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.mrmayhem.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HEADER" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>

Related

RecyclerView Not Loading all items

I am populating Recycler View with a List of 7 string items but Recycler view only loads two of them
by the way my data is long text and it loads all items when text is short
this is my ContentAdapter.java
public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> {
private LayoutInflater mInflater;
private List<String> mContent;
ContentAdapter(Context context, List<String> Content) {
this.mInflater = LayoutInflater.from(context);
mContent = Content;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.rvcontent_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ContentAdapter.ViewHolder holder, int position) {
//loads only two times !?
holder.txtContentPage.setText(mContent.get(position));
}
#Override
public int getItemCount() {
return mContent.size(); // size is 7
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView txtContent;
ViewHolder(View itemView) {
super(itemView);
txtContent = itemView.findViewById(R.id.txtContent);
}
}
}
rvcontent_item.xml
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtContent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.cardview.widget.CardView>
and Activity
rvContents.setNestedScrollingEnabled(false);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
rvContents.setLayoutManager(layoutManager);
ContentAdapter contentAdapter = new ContentAdapter(this, Data); // Data has 7 items
rvContents.setAdapter(contentAdapter);
and this is my layout activity xml
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvContentPage"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
Try with
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:nestedScrollingEnabled="false"
android:focusableInTouchMode="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvContentPage"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
The issue is
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvContentPage"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Here android:layout_height="match_parent" is a bug, since you are inside a scroll view your recyclerview should have height wrap_content. So that the parent will allow it to scroll.
Try changing ConstraintLayout height match_parent instead of wrap_content.
and if persists, Remove scrollView from root because RecyclerView itself makes layout scrollable.

layout inflater its not work i want in onlick functionality

I am not able to to understanding Layout Inflater its not work in correct way please help me one. Layout Infleter if i click that that Images it's not going text page in that i wrote hi hello
public class Add_viewActivity extends AppCompatActivity {
private ImageView cartbtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_view);
cartbtn = findViewById(R.id.cartbtn);
cartbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.text_resource, null);
TextView textid = view.findViewById(R.id.textid);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Add_viewActivity">
<ImageView
android:id="#+id/cartbtn"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_alignParentRight="true"
android:background="#null"
android:src="#drawable/ic_cart_gray"
tools:layout_editor_absoluteX="137dp"
tools:layout_editor_absoluteY="274dp"
tools:ignore="MissingConstraints" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hi hello"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Layout inflator cannot be inflated in on parent's onCreate(). You can only do it in fragment and call it from the parent's onCreate ().

RecyclerView does not display any items when it is in a layout

I have a navigation drawer activity that contains a fragment that contains a RecyclerView. This RecyclerView works perfectly if it is the only component in this fragment, but I want to add a button above the RecyclerView and therefore insert the RecyclerView and the button in a LinearLayout. But then the RecyclerView has disappeared or no longer shows any elements.
How can I embed this RecyclerView in a layout?
RecyclerView works with this one:
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
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/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:name="com.company.myapp.ui.ItemFragment"
app:layoutManager="LinearLayoutManager"
tools:context=".ui.home.HomeFragment"
tools:listitem="#layout/fragment_item" />
RecyclerView has disappeared in this one:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Delete Item" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:name="com.company.myapp.ui.ItemFragment"
app:layoutManager="LinearLayoutManager"
tools:context=".ui.home.HomeFragment"
tools:listitem="#layout/fragment_item" />
</LinearLayout>
See complete project here: https://github.com/jriegraf/MyApp
You have this code in HomeFragment:
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new MyItemRecyclerViewAdapter(DummyContent.ITEMS, mListener));
}
This is your problem. Once you wrap RecyclerView into LinearLayout, this
if (view instanceof RecyclerView)
isn't true any more, because now, view's type is LinearLayout.
If the view doesn't remove the recyclerView, you can ommit the if statement, and change this line:
RecyclerView recyclerView = (RecyclerView) view;
into:
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list);

How to increase the number of text in Android programmatically

I have a page in which I'm taking the START TIME and END TIME from DATABASE.
Let's say the START TIME is 7:00 and END TIME is 22:00
I want to use this START TIME and END TIME to show in my page as textview like 7:00 8:00 9:00 and sooo on till 22:00 as textview
Also I have an imageview that will also increase when the text increases.
How can I achieve this?
Also I want the result text in Horizontal Scroll View with Imageview at top and text view as bottom of each imageview
char first = StartTime.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
int l;
for( l = StartTimeint; l<=22; l++){
Log.d("SeatsPage", "Time is "+l);
}
timeofseats.setText(Integer.toString(l));
This is I have done so far but I'm getting 23 as a result, the textview is not increasing
This is my XML File
<?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:layout_width="match_parent"
android:id="#+id/llMain"
android:layout_height="match_parent"
tools:context=".SeatsPagewithDB.SeatsPage">
<ImageView
android:id="#+id/imageView11"
android:layout_width="150px"
android:layout_height="150px"
android:layout_marginStart="28dp"
android:layout_marginEnd="326dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/seat" />
<TextView
android:id="#+id/timeofseats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="334dp"
android:background="#FF0000"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="7:00"
android:textColor="#fff"
android:textSize="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView11" />
</android.support.constraint.ConstraintLayout>
This is the result I am getting as layout
This what I want programmatically
The XML code that you write in your layout.xml file to create the UI is for static UI only. What you are asking is to create views dynamically during runtime. Although you can definitely create views using java code on a click of a button or something. But it is better to code less for the UI whenever possible and keep it separated from the program code. Instead use the tools given to us by the framework we are using.
In Android those tools include stuff like ListView, GridView and the newer and better RecyclerView. These views help you add other views dynamically to your UI in runtime. You define one of them or more (depending on your UI needs) once in your layout.xml and configure them using java code like any other view.
This is how you can use RecyclerView to achieve your goal. I can't explain everything how RecyclerView works and what each line of code does as it will make a very long post but I have tried to highlight main things briefly.
1. Add RecyclerView in your layout file.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. Create another layout file and define the template UI of the item that the RecyclerView is going to display. RecyclerView will populate each item that it holds with this layout.
item_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/imageView_alarm"
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/alarm" />
<TextView
android:id="#+id/textView_Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="#FF0000"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Time"
android:textColor="#android:color/background_light"
android:textSize="24sp" />
</LinearLayout>
3. Create a ViewHolder class that extends from RecyclerView.ViewHolder. View holder is a RecyclerView related concept. In short it works as a wrapper around the view of a single item and aids in binding new data to the view of the item. Create a bind() function inside view holder to make your life easier.
EDIT: I have updated the class by implementing the View.OnClickListener interface, modified the constructor to pass in the context from onCreateViewHolder() and adding a setItemPosition() just for the sake to pass the item position number from onBindViewHolder() all over to here so we can use this position number in our onClick() method of the interface
MyViewHolder.java [UPDATED]
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textView;
private int itemPosition;
private Context mContext;
public MyViewHolder(#NonNull View itemView, Context context) {
super(itemView);
itemView.setOnClickListener(this);
mContext = context;
textView = itemView.findViewById(R.id.textView_Time);
}
void bind(String timeText)
{
textView.setText(timeText);
}
void setItemPosition(int position)
{
itemPosition = position;
}
#Override
public void onClick(View v) {
Toast.makeText(mContext, "You clicked item number: " + itemPosition , Toast.LENGTH_SHORT).show();
}
}
4. Create an Adapter class that extends from RecyclerView.Adapter. Adapter works as a bridge between the UI data and RecyclerView itself. An Adapter tells the RecyclerView what layout file to inflate and how many to inflate. RecyclerView job is to deal with how to inflate it on the UI.
EDIT : Just changed myViewHolder in onCreateViewHolder() to match the modified constructor of MyViewHolder. Added the call to setItemPosition() in the onBindViewHolder().
MyAdapter.java [UPDATED]
public class MyAdapter extends RecyclerView.Adapter {
List<String> timeIntervalList = new ArrayList<>();
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view , parent.getContext());
return myViewHolder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
MyViewHolder viewHolder = (MyViewHolder) holder;
viewHolder.setItemPosition(position);
viewHolder.bind(timeIntervalList.get(position));
}
#Override
public int getItemCount() {
return timeIntervalList.size();
}
public void addItem (String timeText)
{
timeIntervalList.add(timeText);
notifyItemInserted(getItemCount());
}
}
In this adapter you will see two functions. OnCreateViewHolder() inflates the view using the template layout file for a single item and OnBindViewHolder() binds new data to the default values of the of the view just created. The data used for binding is stored in a list inside this Adapter called the timeIntervalList. This list will hold your time interval strings so they can be updated on the view.
5. Finally, use this RecyclerView where you want to use it. Like in your MainActivity.java. RecyclerView needs to be told in what fashion to display the items (e.g list , grid etc ) using a LayoutManager. LinearLayoutManager will display items either vertically or horizontally. You can see I am using your logic to increment time from string and adding new views to RecyclerView using the addItem() function of the MyAdapter class.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView myRecyclerView;
private MyAdapter myAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myRecyclerView = findViewById(R.id.recyclerView);
myAdapter = new MyAdapter();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this , LinearLayoutManager.HORIZONTAL, false);
myRecyclerView.setLayoutManager(linearLayoutManager);
myRecyclerView.setAdapter(myAdapter);
// This is how you will populate the recycler view
String START_TIME = "7:00";
String END_TIME = "22:00";
char first = START_TIME.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
int l;
for( l = StartTimeint; l<=22; l++){
// This is where new item are added to recyclerView.
myAdapter.addItem(l + ":00");
}
}
}
This is the final result.
Change your activity layout XML code as follows,
<?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:layout_width="match_parent"
android:id="#+id/llMain"
android:layout_height="match_parent"
tools:context=".SeatsPagewithDB.SeatsPage">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
...
...>
<LinearLayout
android:id="#+id/container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
</android.support.constraint.ConstraintLayout>
Move the textview and imageview to another XML file let's call it item_view.xml (you can name it whatever you wish). we are doing so because the root view of this file will be reused.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView11"
android:layout_width="150px"
android:layout_height="150px"
app:srcCompat="#drawable/seat"/>
<TextView
android:id="#+id/timeofseats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="7:00"
android:textColor="#fff"
android:textSize="20dp"/>
</LinearLayout>
Now make following changes in your Java file
LinearLayout container = findViewById(R.id.container); // or rootView.findViewById() for custom View and Fragment
char first = StartTime.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
for(int l = StartTimeint; l<=22; l++){
Log.d("SeatsPage", "Time is "+l);
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_view, null);
TextView timeofseats = view.findViewById(R.id.timeofseats);
timeofseats.setText(Integer.toString(l));
container.addView(view);
}

ListView only shows first item

I want to display all items of an ArrayList<String> on a ListView. I use an ArrayAdapter<String> for this. The problem is that only the first item ('foo' in my example) of the ArrayList is shown. Can someone tell me why? Am I missing something?
I've made an minimal example using the generated code (Tabbed Action Bar Spinner Activity) from Android Studio 2.
My FooActivity:
public class FooActivity extends AppCompatActivity {
...
public static class PlaceholderFragment extends Fragment {
private ListView fooListView;
private ArrayAdapter<String> mAdapter;
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_foo, container, false);
fooListView = (ListView) rootView.findViewById(R.id.foo_list);
updateList();
return rootView;
}
private void updateList() {
ArrayList<String> strings = new ArrayList<>();
strings.add("foo");
strings.add("bar");
if (mAdapter == null) {
mAdapter = new ArrayAdapter<>(getContext(),
R.layout.item_foo,
R.id.foo_string,
strings);
fooListView.setAdapter(mAdapter);
} else {
mAdapter.clear();
mAdapter.addAll(strings);
mAdapter.notifyDataSetChanged();
}
}
}
My fragment_foo.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.foo.activities.FooActivity$PlaceholderFragment">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/foo_list"
android:layout_below="#+id/total_activities"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="10dp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
And the item_foo.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/foo_string"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="some_string"
android:textSize="20sp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</LinearLayout>
If it helps I can post the generated activity_foo.xml (I didn't made any changes there) and the complete FooActivity class too.
The Problem actually was my activity_foo.xml which had a NestedScrollView. I've added android:fillViewport="true" and now it shows every item.
My NestedScrollView now looks like this:
<android.support.v4.widget.NestedScrollView
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true"/>
On any ListView, if you use android:layout_height="wrap_content", you're only going to see one item. Try android:layout_height="match_parent". If the ListView only takes up part of the layout, you'll need a LinearLayout with weights or a RelativeLayout with constraints. But wrap_content won't work for a height on a ListView, ever.
Your Listview look something like this
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/foo_list"
android:layout_marginTop="10dp"/>
I have removed from your list view android:layout_below="#+id/total_activities"
and
android:layout_alignParentBottom="true"
For others: It's okay to nest a ListView inside another layout, and it's also fine to use android:layout_height="wrap_content" on Layouts surrounding the ListView. (So long as the outer-most Layout allows for match_parent)
What is not fine, however, is when the TextView being used to populate the ListView is defined with layout_height="match_parent". It will cover up all of the subsequent rows after the first.
Bad:
<TextView
android:id="#+id/infoRow_textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Good:
<TextView
android:id="#+id/infoRow_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>

Categories