I'm creating a calendar app, with each month being displayed using a RecylcerView. Inside each day of each month, there is another RecyclerView to display events on that day. I'm using the custuomLinearLayoutManager from https://stackoverflow.com/a/38513905/13199395, and I've looked at many examples. My code for the nesting is very similar to them but for some reason is not working. Any help as to why is not working would be much appreciated.
The month view:
<FrameLayout 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"
tools:context=".MonthViewActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/calView"
android:layout_width="match_parent"
android:layout_height="581dp"
android:layout_gravity="bottom" />
</FrameLayout>
The view for each day:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/dayView"
android:layout_width="145px"
android:layout_height="265px"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/eventDayView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
and the view for the inner recyclerView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/showEvents"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/eventName"
android:layout_width="145px"
android:layout_height="wrap_content" />
</LinearLayout>
The adapter for the main recyclerview:
public class MonthViewAdapter extends RecyclerView.Adapter<MonthViewAdapter.ViewHolder> {
Context context;
ArrayList<Day> days;
CustomLinearLayoutManager l;
public MonthViewAdapter(Context context, ArrayList<Day> arrayList) {
this.context = context;
this.days = arrayList;
}
#NonNull
#Override
public MonthViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.content_events, parent, false);
return new ViewHolder(view, this.mOnDayClickListener);
}
#Override
public void onBindViewHolder(MonthViewAdapter.ViewHolder holder, int position) {
l = new CustomLinearLayoutManager(context, LinearLayout.VERTICAL, false);
ViewGroup.LayoutParams params=holder.r.getLayoutParams();
params.height=100;
holder.r.setLayoutParams(params);
holder.r.setLayoutManager(l);
EventViewAdapter adapter = new EventViewAdapter(context, days.get(position).getEvents(), this.mOnDayClickListener);
holder.r.setAdapter(adapter);
holder.t.setText(days.get(position).getMonthDayNumber());
}
#Override
public int getItemCount() {
return days.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RecyclerView r;
TextView t;
FrameLayout f;
LinearLayout l;
public ViewHolder(View itemView) {
super(itemView);
l = itemView.findViewById(R.id.dayView);
t = itemView.findViewById(R.id.dayNum);
r = itemView.findViewById(R.id.eventDayView);
}
}
}
The adapter for the inner RecyclerView:
public class EventViewAdapter extends RecyclerView.Adapter<EventViewAdapter.ViewHolder> {
Context context;
ArrayList<Event> events;
public EventViewAdapter (Context context, ArrayList<Event> arrayList) {
this.context = context;
this.events = arrayList;
}
#Override
public EventViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.content_single_event, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(EventViewAdapter.ViewHolder holder, int position) {
Log.d("event", Integer.toString(events.size()));
holder.eventName.setText(events.get(position).getName());
}
#Override
public int getItemCount() {
return events.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView eventName;
LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
eventName = itemView.findViewById(R.id.eventName);
linearLayout = itemView.findViewById(R.id.showEvents);
}
}
}
The custom linear layout manager: https://stackoverflow.com/a/38513905/13199395
And the activity
public class MonthViewActivity extends AppCompatActivity{
RecyclerView month;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_month_view);
month.setHasFixedSize(true);
month.addItemDecoration(new DividerItemDecoration(this,
DividerItemDecoration.HORIZONTAL));
month.addItemDecoration(new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL));
GridLayoutManager g = new GridLayoutManager(this, 7);
month.setLayoutManager(g);
ArrayList<Day> day = new ArrayList<>();
LocalDate dd = LocalDate.now();
Day d1 = new Day(dd);
Day d2 = new Day(dd.plusDays(1));
Day d3 = new Day(dd.plusDays(2));
d1.addEvent(new Event("a"));
day.add(d1);
adapter = new MonthViewAdapter(this, day, this);
month.setAdapter(adapter);
}
}
Each element of the list that I pass into the month view adapter has a list of events that are then passed into the event adapter. However, each day in the grid only shows one of the events, it does not show all of the events in the event list on each day. Why is this happening and how can I fix it? I am getting an error (java.lang.IndexOutOfBoundsException: Invalid item position) on
View view = recycler.getViewForPosition(position);
in the custom layout manager, but the program does not crash.
Related
Im trying to create a bunch of rows in a Listview to show from an ArrayList of object class
my object class Locations has
private String name;
private int currentCapacity;
private int maxCapacity;
private int id;
public Locations(String name, int currentCapacity, int maxCapacity, int id){
this.currentCapacity = currentCapacity;
this.id = id;
this.maxCapacity = maxCapacity;
this.name = name;
}
Locations loc1 = new Locations("foodplace", 10, 100, 1);
Locations loc2 = new Locations("area", 15, 25, 2);
Locations loc3 = new Locations("otherplace", 25, 25, 3);
locationsArrayList.add(loc1);
locationsArrayList.add(loc2);
locationsArrayList.add(loc3);
ListView list = (ListView) findViewById(R.id.theList);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, locationsArrayList);
list.setAdapter(adapter);
how do i input my ArrayList such that i can change the color of the row based on the currentCapacity and show the name on the block?
You have to use RecyclerView
//Declare some items in your ArrayList
Locations loc1 = new Locations("foodplace", 10, 100, 1);
Locations loc2 = new Locations("area", 15, 25, 2);
Locations loc3 = new Locations("otherplace", 25, 25, 3);
locationsArrayList.add(loc1);
locationsArrayList.add(loc2);
locationsArrayList.add(loc3);
//make your own adapter class which extend RecyclerView.Adapter
MyAdapter myAdapter = new MyAdapter(locationsArrayList,this);
//setup your RecylerView
recyclerView.setAdapter(itemsListAdapter);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
Now in your Adapter class you can change each item color or font... based on ArrayList attribute.
public class MyAdapter extends RecyclerView.Adapter{
private ArrayList<Location> locationsArrayList;
private Context context;
public MyAdapter(ArrayList<Location> locationsArrayList, Context context) {
this.locationsArrayList= locationsArrayList;
this.context = context;
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(context)
.inflate(R.layout.item_layout,parent,false));
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
ViewHolder viewHolder = (ViewHolder) holder;
//here you can set your own conditions based on your arraylist using position parameter
viewHolder.itemNameTextView.setText(locationsArrayList.get(position).getName());
}
#Override
public int getItemCount() {
return locationsArrayList.size();
}
public Context getContext() {
return context;
}
class ViewHolder extends RecyclerView.ViewHolder {
//setup item layout attributes
TextView itemNameTextView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemNameTextView = itemView.findViewById(R.id.itemNameTextView);
}
}
}
I know it's complicated but RecyclerView make your list more flexible.
Hie i would suggest you use RecyclerView to achieve your list view
if you are using gradle for your dependencies you need to implement it in your app level gradle file
In your activity.xml file you implement like this
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/locations_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And then create a item file that will represent item in a list item
for example lets call it location_list_item.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="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp"
>
<TextView
android:id="#+id/location_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<TextView
android:id="#+id/max_capacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<TextView
android:id="#+id/current_capacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
</LinearLayout>
Then after that you would need to implement an Adapter lets call it LocationAdapter.java
public class LocationAdapter extends RecyclerView.Adapter<LocationAdapter.ViewHolder> {
ArrayList<Location> locations;//list of locations
public LoacationAdapter(ArrayList<Location> locations) {
this.locations = locations //initialising list in constructor
}
#NonNull
#Override
public Locations.Adapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//here this method inflates the row view
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.location_list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull LocationAdapter.ViewHolder holder, int position) {
//this method sets values in the views
holder.locationName.settext(locations.get(position).getLocationName())
holder.maxCapacity.settext(locations.get(position).getMaxCapacity())
holder.currentCapacity.settext(locations.get(position).getCurrentCapacity())
}
#Override
public int getItemCount() {
return locatioins.size();// number of locations
}
//this class will repressent the list item
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
// this are the views in the list item
TextView locationName, maxCapacity, currrentCapacity;
public ViewHolder(#NonNull View itemView) {
super(itemView);
locationName = itemView.findViewById(R.id.location_name);
maxCapacity= itemView.findViewById(R.id.max_capacity);
currentCapacity= itemView.findViewById(R.id.current_capacity);
itemView.setOnClickListener(this::onClick);
}
#Override
public void onClick(View v) {
//do what ever you want when an item is clicked
}
}
}
In in your activity file then
ArrayList<Location> locationsArraylist = new ArrayLists<> ();
//initializing recylcer view
RecyclerView locationList = findViewById(R.id.locations_list);
// setting layout manager
locationsList.setLayoutManager(new LinearLayoutManager(getContext, RecyclerView.Vertical, false));
//setting adapter adapter with the list of locations you want to display
locationList.setAdapter(new LocationsAdapter(locationsArraylist));
I want to create the following UI with a single list of dataset.
I tried using multiple view type but could not achieve my requirement. I also implemented this blog Android Horizontal and Vertical RecyclerView Example.
But this uses two recyclerviews and there are two sets of data (horizontal data and vertical data).
I also have tried this one. RecyclerView with multiple views using custom adapter in Android
But this is using static card views in XML and loading them in adapter.
I'm beginner in Android development. Please help!
Thank you in advance.
Your desired layout can be achieved by using a GridLayoutManager along with two "item view types" inside your RecyclerView.Adapter.
Here are my layout XML files:
activity_main.xml:
-------------------------
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
horizontal.xml:
-------------------------
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_margin="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/image"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ccc"/>
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:background="#fff"
android:textColor="#000"
android:textSize="18sp"
android:text="TEXT"/>
</LinearLayout>
</android.support.v7.widget.CardView>
vertical.xml:
-------------------------
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_margin="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#ccc"/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="#fff"
android:textColor="#000"
android:textSize="18sp"
android:text="TEXT"/>
</LinearLayout>
</android.support.v7.widget.CardView>
And here is my Java file:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GridLayoutManager manager = new GridLayoutManager(this, 2);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return (position % 4) < 2 ? 2 : 1;
}
});
RecyclerView recycler = (RecyclerView) findViewById(R.id.recycler);
recycler.setLayoutManager(manager);
recycler.setAdapter(new MyAdapter());
}
private static class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
#Override
public int getItemViewType(int position) {
return (position % 4) < 2
? R.layout.horizontal
: R.layout.vertical;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(viewType, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.image.setImageResource(R.drawable.mouse);
holder.text.setText("" + position);
}
#Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
}
private static class MyViewHolder extends RecyclerView.ViewHolder {
private final ImageView image;
private final TextView text;
public MyViewHolder(View itemView) {
super(itemView);
this.image = (ImageView) itemView.findViewById(R.id.image);
this.text = (TextView) itemView.findViewById(R.id.text);
}
}
}
Let's go over the important parts. First up is the combination of GridLayoutManager and SpanSizeLookup. We're creating the layout manager with this line:
GridLayoutManager manager = new GridLayoutManager(this, 2);
Which means that, by default, there will be two cards in each row of our grid. But then we apply the SpanSizeLookup, which says that half of our rows (found by the statement position % 4 < 2) should actually take up two columns. So we'll have one card, one card, two cards repeating in our "grid".
Then, in the RecyclerView.Adapter class, we override the getItemViewType() method. Here we again use the position % 4 < 2 statement to say that half of our views should be horizontal, and half should be vertical.
getItemViewType() just needs to return any unique int for each view type, so we use a nice trick of returning R.layout constants from this method. Since the view type will then be passed into onCreateViewHolder(), we can use the viewType argument to inflate the correct layout.
And that's it! Not too bad after all. Here's a screenshot of my code in action:
I had this issue not too long ago, though I may not be an expert I think my answer can help you as well. You can do this by creating two different types of layouts, similar to the article. You need to create an abstract class that both of the layout types can extend. Then, in your adapter, check what type of object should be shown.
Abstract class:
public abstract class ListItem {
public static final int TYPE_HORIZONTAL = 0;
public static final int TYPE_VERTICAL = 1;
abstract public int getType();
}
Horizontal Item:
public class HorizontalItem extends ListItem {
private String text;
private Bitmap image;
public HorizontalItem(String text, Bitmap image) {
this.text = text;
this.image = image;
}
/*
* Getter and setter methods here
*/
#Override
public int getType() {
return ListItem.TYPE_HORIZONTAL;
}
}
Vertical Item:
public class VerticalItem extends ListItem {
private String text1;
private Bitmap image1;
private String text2;
private Bitmap image2;
public VerticalItem(String text1, String text2, Bitmap image1, Bitmap image2) {
this.text1 = text1;
this.image1 = image1;
this.text2 = text2;
this.image2 = image2;
}
/*
* Getter and setter methods here
*/
#Override
public int getType() {
return ListItem.TYPE_HORIZONTAL;
}
}
Adapter:
public class ListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<ListItem> listItems;
public static class HorizontalViewHolder extends RecyclerView.ViewHolder {
public TextView text;
public ImageView imageView;
public HorizontalHolder(View v) {
super(v);
text = (TextView) v.findViewById(R.id.text);
imageView = (ImageView) v.findViewById(R.id.imageView);
}
}
public static class VerticalViewHolder extends RecyclerView.ViewHolder {
public TextView text1;
public ImageView imageView1;
public TextView text2;
public ImageView imageView2;
public HorizontalHolder(View v) {
super(v);
text1 = (TextView) v.findViewById(R.id.text1);
imageView1 = (ImageView) v.findViewById(R.id.imageView1);
text2 = (TextView) v.findViewById(R.id.text2);
imageView2 = (ImageView) v.findViewById(R.id.imageView2);
}
}
// constructor
public ListAdapter(ArrayList<ListItem> listItems) {
this.listItems = listItems;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
RecyclerView.ViewHolder holder = null;
switch (viewType) {
case ListItem.TYPE_HORIZONTAL:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.template_horizontal, parent, false);
holder = new HorizontalViewHolder(v);
break;
case ListItem.TYPE_VERTICAL:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.template_vertical, parent, false);
holder = new VerticalViewHolder(v);
break;
}
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case ListItem.TYPE_HORIZONTAL:
((HorizontalViewHolder) holder).text.setText(listItems.get(position).getText());
((HorizontalViewHolder) holder).imageView.setImageBitmap(listItems.get(position).getBitmap());
// the getText() and getBitmap() methods come from the getters of the HorizontalItems and VerticalItems that are stored in the ArrayList, listItems
break;
case ListItem.TYPE_DECK:
// Identical to above
break;
}
}
#Override
public int getItemCount() {
return listItems.size();
}
// This is extremely important, it is what lets the adapter know what type each listItem element is
#Override
public int getItemViewType(int position) {
return listItems.get(position).getType();
}
}
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
// Must be of abstract type ListItem
ArrayList<ListItem> items = new ArrayList<>();
// populate your ArrayList
items.add(new HorizontalItem("text", bitmap));
items.add(new VerticalItem("text1", "text2", bitmap1, bitmap2));
// ... and so on
ListAdapter adapter = new ListAdapter(items)
RecyclerView recycler = (RecyclerView) findViewById(R.id.recycler);
recycler.setAdapter(adapter);
recycler.setLayoutManager(new LinearLayoutManager(this));
// ... the rest of your code below
}
In your layout for the vertical list item, I would just create one file with two halves to it. You can use a LinearLayout to easily divide the subsections into perfect halves.
I would like to use RecycleView for displaying my array of data.
This is my Adapater class which is setting data on view.
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder>{
private Context context;
private List<Pojo> dataList;
public DataAdapter(Context context, List<Pojo> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_main,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.categoryTV.setText(dataList.get(position).getGameName());
}
#Override
public int getItemCount() {
return dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView categoryTV;
public MyViewHolder(View itemView) {
super(itemView);
categoryTV = (TextView) itemView.findViewById(R.id.text);
}
}
}
This is my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="#+id/rellayout"
tools:context="com.acknotech.kiran.retrofit_second.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/text"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
This is MainActivity..
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private DataAdapter dataAdapter;
private List<Pojo> dataArrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
recyclerView=(RecyclerView) findViewById(R.id.my_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
loadJSON();
}
private void loadJSON(){
dataArrayList = new ArrayList<>();
Retrofit retrofit=new Retrofit.Builder().baseUrl("my url").addConverterFactory(GsonConverterFactory.create()).build();
AllGamesAPI requestInterface=retrofit.create(AllGamesAPI.class);
Call<List<Pojo>> call= requestInterface.getJSON();
call.enqueue(new Callback<List<Pojo>>() {
#Override
public void onResponse(Call<List<Pojo>> call, Response<List<Pojo>> response) {
dataArrayList = response.body();
dataAdapter=new DataAdapter(getApplicationContext(),dataArrayList);
recyclerView.setAdapter(dataAdapter);
}
#Override
public void onFailure(Call<List<Pojo>> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
}
}
When i try to execute it always printing only one item at a time but in dataList i have 11 items.
How to use RecyclerView to get all items in a page?
Thanks & Regards
You shouldn't inflate the activities layout in onCreateViewHolder, but instead inflate a layout for only one item (e.g. android.R.layout.simple_list_item_1, or a custom one). This layout should not use match_parent for the height of items.
I am working on a college project to build an android based mobile learning app. I'm using Parse for backend services. There is a class, namely 'Course' which contains name of the courses to be offered along with an icon for each course. I have written code for custom adapter to display a list of all the courses with icons. The project is executing but the list is not appearing. I cannot figure out what is going wrong.
Here is my SelectCourse.java code
final List<Item> items=new ArrayList<Item>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("Course");
query.orderByAscending("name");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> list, ParseException e) {
if (e == null) {
if (list.size() > 0)
for (int i = 0; i < list.size(); i++) {
final String course = list.get(i).getString("name");
ParseFile image = list.get(i).getParseFile("image");
//adapter.add(course.getString("name"));
image.getDataInBackground(new GetDataCallback() {
public void done(byte[] data, ParseException e) {
if (e == null) {
Bitmap icon = BitmapFactory.decodeByteArray(
data, 0, data.length);
Item item = new Item(icon, course);
items.add(item);
} else {
Toast.makeText(getApplicationContext(),
e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
});
}
} else {
Toast.makeText(getApplicationContext(),
e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
});
CustomAdapter adapter=new CustomAdapter(this,items);
ListView listView = (ListView) findViewById(R.id.course_list);
listView.setAdapter(adapter);
This is my CustomAdapter.java code
public class CustomAdapter extends BaseAdapter {
private Context context;
private List<Item> list;
CustomAdapter(Context context, List<Item> list){
this.context = context;
this.list = list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView=convertView;
if(rowView==null) {
ViewHolder viewHolder = new ViewHolder();
LayoutInflater layoutInflater = (LayoutInflater) context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = layoutInflater.inflate(R.layout.list_select_course, parent, false);
viewHolder.icon = (ImageView) rowView.findViewById(R.id.rowImageView);
viewHolder.text = (TextView) rowView.findViewById(R.id.rowTextView);
rowView.setTag(viewHolder);
}
ViewHolder viewHolder = (ViewHolder) rowView.getTag();
viewHolder.icon.setImageBitmap(list.get(position).image);
viewHolder.text.setText(list.get(position).text);
return rowView;
}}
Here are ViewHolder and Item
public class ViewHolder {
ImageView icon;
TextView text;}
public class Item {
Bitmap image;
String text;
Item(Bitmap image, String text){
this.image=image;
this.text=text;
}}
This is content_select_course.xml
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.rsa.minerva.SelectCourseActivity"
tools:showIn="#layout/app_bar_select_course">
<ListView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/course_list"
android:layout_weight="1" />
And finally list_select_course.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:id="#+id/rowImageView"
android:layout_width="48dp"
android:layout_height="48dp" />
<TextView
android:id="#+id/rowTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/colorButton"
android:text="Hello World"/>
This part of the code:
query.findInBackground(new FindCallback<ParseObject>()
Doesn't run synchronously, meaning that you are actually creating an adapter with no data:
Put this snippet before you call the query.findInBackground():
CustomAdapter adapter=new CustomAdapter(this,items);
ListView listView = (ListView) findViewById(R.id.course_list);
listView.setAdapter(adapter);
And then inside the public void done() callback, put:
adapter.notifyDataSetChanged();
After you add the items to the list with items.add(item).
That should do it.
I'm learning Android SDK and I need some advices.
I have custom ListView with BaseAdapter and I want to implement some new feature - Favorite Button.
What I want to do is, when I press the Favorite Button, ListItem goes to the beginning of the list, Favorite image change and all that stuff will be saved in the SharedPrefs.
Someone tell me what I need to do, to make it works?
my existing code:
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layout_element_list"
>
<ImageView
android:id="#+id/icon"
android:layout_width="150dp"
android:padding="5dp"
android:layout_height="150dp"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="#drawable/radio" >
</ImageView>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/label"
android:paddingTop="20dp"
android:layout_gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:textAlignment="center"
android:text="RadioName"
android:textColor="#color/color1"
android:textSize="30dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<TextView
android:id="#+id/label2"
android:layout_gravity="center_vertical"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="fill_parent"
android:textAlignment="center"
android:text="Description.."
android:textColor="#color/color1"
android:textSize="15dp" />
<ImageView
android:id="#+id/favButton"
android:layout_weight="1"
android:layout_width="fill_parent"
android:padding="5dp"
android:layout_height="fill_parent"
android:layout_marginLeft="4px"
android:layout_marginRight="10px"
android:layout_marginTop="4px"
android:src="#drawable/fav_off" >
</ImageView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
BaseAdapter class:
public class RadioAdapter extends BaseAdapter
{
ArrayList<RadioStation> myList = new ArrayList<RadioStation>();
LayoutInflater inflater;
Context context;
public RadioAdapter(Context context, ArrayList<RadioStation> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public RadioStation getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.activity_menu_row, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.label, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.label2, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.icon, myList.get(position).getImgResId());
return convertView;
}
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
RadioStation class:
public class RadioStation
{
public String title;
public String description;
public int imgResId;
//getters and setters
public static Comparator<RadioStation> comparatorByRadioName = new Comparator<RadioStation>()
{
#Override
public int compare(RadioStation radioStation, RadioStation radioStation2)
{
String name1 = radioStation.getTitle().toLowerCase();
String name2 = radioStation2.getTitle().toLowerCase();
return name1.compareTo(name2);
}
};
}
ActivityListView:
public class ActivityMenuList extends Activity implements AdapterView.OnItemClickListener
{
private ListView lvDetail;
private Context context = ActivityMenuList.this;
private ArrayList <RadioStation> myList = new ArrayList <RadioStation>();
private String[] names = new String[] { "one", "two", "three" };
private String[] descriptions = new String[] { "notset", "notset", "notset"};
private int[] images = new int[] { R.drawable.one, R.drawable.two, R.drawable.three };
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().setBackgroundDrawableResource(R.drawable.bg1);
setContentView(R.layout.activity_menu_list);
lvDetail = (ListView) findViewById(R.id.list);
lvDetail.setOnItemClickListener(this);
getDataInList();
lvDetail.setAdapter(new RadioAdapter(context, myList));
}
private void getDataInList() {
for(int i=0;i<3;i++) {
RadioStation ld = new RadioStation();
ld.setTitle(names[i]);
ld.setDescription(descriptions[i]);
ld.setImgResId(images[i]);
myList.add(ld);
}
Collections.sort(myList, RadioStation.comparatorByRadioName);
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
{
String item = names[i];
Intent e = new Intent(ActivityMenuList.this, ActivityRadioStation.class);
Bundle data = new Bundle();
data.putString("radiostation",item);
e.putExtras(data);
startActivity(e);
}
}
That's a lot of changes you have to do. Let's start with the basic.
Add a boolean to your RadioStation for the favorite state.
public boolean isFavorite;
Next on your getView add the favorite button click listener(add its reference to the viewholder too, but let's keep it simple this time)
public class RadioAdapter extends BaseAdapter
{
ArrayList<RadioStation> myList = new ArrayList<RadioStation>();
LayoutInflater inflater;
Context context;
ListView mListview;
public RadioAdapter(Context context, ArrayList<RadioStation> myList, ListView list) {
this.myList = myList;
this.context = context;
mListView = list;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public RadioStation getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.activity_menu_row, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.label, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.label2, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.icon, myList.get(position).getImgResId());
convertView.findViewById(R.id.favButton).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
myList.get(position).isFavorite=! myList.get(position).isFavorite;
//reorder mlist
notifyDataSetChanged();
//mListView. smoothscroll here
}
});
((ImageView) convertView.findViewById(R.id.favButton)).setImageResource(myList.get(position).isFavorite?R.drawable.favoriteOn:R.drawable.favoriteOff);
return convertView;
}
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
I left commented what you should do on the listener. You should be able to continue from here.
When you create your adapter pass the list as the last parameter on the constructor.
Edited: Removed interface. No need to use it here.