Error Shown:
Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference.
The error surface at the gridView.setAdapter(adapter); but am able to print response from API only to pass it to the adapter for layout to handle the display.
Am suggesting converting the Model Class into a list of array of which is not actually going my way.
Have tried modelName.toArray() and many others.
Thank you as i await your response.
My Model Class
public class MensWear {
private int id, user_id;
private String first_wear;
public MensWear(int id,int user_id,String first_wear) {
this.id = id;
this.user_id = user_id;
this.first_wear = first_wear;
}
public int getId() {
return id;
}
public int getUser_id() {
return user_id;
}
public String getFirst_wear() {
return first_wear;
}
}
My Base Adapter Class
public class PhoneAdapter extends BaseAdapter {
private Context context;
private List<MensWear> mensWears;
public String imageUrlFromServer = "http:/10.0.2.2:5757/api/public/images/";
public PhoneAdapter(Context context, List<MensWear> mensWears) {
this.context = context;
this.mensWears = mensWears;
}
#Override
public int getCount() {
return mensWears.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i,View view,ViewGroup viewGroup) {
final MensWear mensWear = mensWears.get(i);
if (view == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.phone_list, null);
}
//For text
TextView prdId = view.findViewById(R.id.mensWearIdForHompePage);
prdId.setText(prdId.toString());
//For images
final ImageView imageView = view.findViewById(R.id.phoneImages);
if(!TextUtils.isEmpty(mensWear.getFirst_wear())){
Picasso.with(context).load(imageUrlFromServer+mensWear.getFirst_wear())
.into(imageView);
}
return view;
}
}
My Class extending Fragment
public class Phones extends Fragment {
private GridView gridView;
private List<MensWear> mensWears;
private PhoneAdapter adapter;
public Phones() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_phones,container,false);
}
#Override
public void onViewCreated(#NonNull View view,#Nullable Bundle savedInstanceState) {
super.onViewCreated(view,savedInstanceState);
gridView = view.findViewById(R.id.gridHolder);
gridView = view.findViewById(R.id.gridHolder);
Call<MensWearResponse> wearResponseCall =
Service.getInstance().getApi().getAllMensWears();
wearResponseCall.enqueue(new Callback<MensWearResponse>() {
#Override
public void onResponse(Call<MensWearResponse> call,Response<MensWearResponse> response) {
mensWears = response.body().getMensWears();
for (MensWear mwr : mensWears){
Log.d("Name", mwr.getFirst_wear());
}
adapter = new PhoneAdapter(getActivity(), mensWears);
gridView.setAdapter(adapter);
}
#Override
public void onFailure(Call<MensWearResponse> call,Throwable t) {
}
});
}
}
My Layout Files
The Grid Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context="com.nelbuc.nelbuc.goodWears"
>
<Grid
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:columnWidth="100dp"
android:numColumns="2"
android:verticalSpacing="24dp"
android:horizontalSpacing="10dp"
android:stretchMode="spacingWidthUniform"
android:id="#+id/gridHolder"
>
</Grid>
</RelativeLayout>
The List Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/phoneList"
android:layout_width="190dp"
android:background="#fff"
android:layout_height="180dp"
>
<TextView
android:id="#+id/mensWearIdForHompePage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Apple"
android:textStyle="normal|italic"
android:textSize="25dp" />
<ImageView
android:id="#+id/phoneImages"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
</RelativeLayout>
</RelativeLayout>
Error message clearly says that GridView is null. There is no GridView in your layout, there is only Grid. Change Grid to GridView.
In your layout, You are using only Grid. Change from Grid to GridView
Create ArrayList and add the model i.e MensWear into that list like this following and then pass this list into your adpater:
ArrayList<MensWear > arrayList_mens = new ArrayList<MensWear>();
for (MensWear mwr : mensWears)
{
Log.d("Name", mwr.getFirst_wear());
arrayList_mens.add(mwr);
}
Related
I am developing an app in which I am showing users data in a recyclerview. I have used a library which shows preview of a url.
My Problem
Each user has video1, video2, and video3 nodes and I want to display the data of each user 3 times i.e. in the first itemView I want to display video1, in the 2nd video2, and in the 3rd video3. So each user will have 3 itemViews. Below is my code. Please do ask if you need any clarification. Thanks in advance
[![Database Struction][1]][1]
[1]: https://i.stack.imgur.com/XJQqt.png
Adapter Class
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
Context context;
ArrayList<ModelClass> modelClass = new ArrayList<>();
public MyAdapter(Context context, ArrayList<ModelClass> modelClass) {
this.context = context;
this.modelClass = modelClass;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.gig_display_layout, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.urlEmbeddedView.setURL(modelClass.get(position).getVideo1(), new URLEmbeddedView.OnLoadURLListener() {
#Override
public void onLoadURLCompleted(URLEmbeddedData data) {
holder.urlEmbeddedView.title(data.getTitle());
holder.urlEmbeddedView.description(data.getDescription());
holder.urlEmbeddedView.host(data.getHost());
holder.urlEmbeddedView.thumbnail(data.getThumbnailURL());
holder.urlEmbeddedView.favor(data.getFavorURL());
}
});
}
#Override
public int getItemCount() {
return modelClass.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
URLEmbeddedView urlEmbeddedView;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
urlEmbeddedView = itemView.findViewById(R.id.urlView);
}
}
}
Model Class
public class ModelClass {
public String name, video1, video2, video3, videos;
int showVideoCount = 1;
int lifeTimeClicks = 0;
int lifeTimeClicksOnProfile = 0;
int dailyClicksOnProfile = 0;
int dailyClicksByYou = 0;
public ModelClass(String name, String video1, String video2, String video3) {
this.name = name;
this.video1 = video1;
this.video2 = video2;
this.video3 = video3;
}
public ModelClass() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVideo1() {
return video1;
}
public void setVideo1(String video1) {
this.video1 = video1;
}
public String getVideo2() {
return video2;
}
public void setVideo2(String video2) {
this.video2 = video2;
}
public String getVideo3() {
return video3;
}
public void setVideo3(String video3) {
this.video3 = video3;
}
HomeFragment
dRef.addListenerForSingleValueEvent(new ValueEventListener() { // singleValueEvent will only call the firebase database once
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
list = new ArrayList<ModelClass>();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
ModelClass modelClass = dataSnapshot.getValue(ModelClass.class);
list.add(modelClass);
Collections.shuffle(list); // This will shuffle the links
}
MyAdapter adapter = new MyAdapter(getActivity(), list);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
Sir Use Nested Recyclerview, Inside your main Item view in xml use another recyclerview.
e.g:
MainAcitivty.xml
<android.support.constraint.ConstraintLayout
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"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.constraint.ConstraintLayout>
FirstItem.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#f3f3f3"
app:cardElevation="8dp"
android:layout_margin="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:orientation="vertical">
<TextView
android:id="#+id/tv_item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12sp"
android:textSize="18sp"
android:text="Item Title"/>
//recycler for video
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_sub_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
SubItem.xml (for displaying videos) :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_sub_item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="Sub item title"/> //Video
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
you have model and adapter for MainItem already, Now create model and adapter for subitem(for videos), now in onBindViewHolder of the MainItemAdapter, set subItem layout, also initialize in ItemViewHolder in MainItemAdapter.
e.g. something like this
#Override
public void onBindViewHolder(#NonNull ItemViewHolder itemViewHolder, int i) {
LinearLayoutManager layoutManager = new LinearLayoutManager(
itemViewHolder.rvSubItem.getContext(),
LinearLayoutManager.VERTICAL,
false
);
// Create sub item view adapter
SubItemAdapter subItemAdapter = new SubItemAdapter(item.getSubItemList());
itemViewHolder.rvSubItem.setLayoutManager(layoutManager);
itemViewHolder.rvSubItem.setAdapter(subItemAdapter);
itemViewHolder.rvSubItem.setRecycledViewPool(viewPool);
}
class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView tvItemTitle;
private RecyclerView rvSubItem;
ItemViewHolder(View itemView) {
super(itemView);
tvItemTitle = itemView.findViewById(R.id.tv_item_title);
rvSubItem = itemView.findViewById(R.id.rv_sub_item);
}
}
I have populated weight conversion functionality on listview using string array. I want to change the values of each entity when new value is typed by the user on any entity i.e KG, Pound and Gram. But addTextChangedListener is not responding properly and values are getting wrong on each EditText.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
convAdapter adapter = new convAdapter(MainActivity.this);
ListView list = findViewById(R.id.unitc_list);
list.setAdapter(adapter);
}
}
convAdapter.java
public class convAdapter extends BaseAdapter {
static TextWatcher watcher=null;
DecimalFormat format = new DecimalFormat("0.########");
private String unitWeight[] = {"Pound","Kilogram","Gram"};
private static String unitWeightValue[] = {"2.204","1","1000"};
private String unitWeightValueUpdated[] = unitWeightValue;
private static Activity activity;
private static LayoutInflater inflater=null;
public convAdapter(Activity a) {
activity = a;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return unitWeight.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView==null){
convertView = inflater.inflate(R.layout.unit_row, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txtItem.setText(unitWeight[position]);
viewHolder.etValue.setText(format.format(((double) Math.round(10000*Double.parseDouble(unitWeightValueUpdated[position]))/10000.0)));
viewHolder.txtItem.setTag(position);
viewHolder.etValue.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void afterTextChanged(Editable s) {
if(unitWeight[position].equals("Kilogram")){
int i = 0;
for(String pos: unitWeightValue ){
unitWeightValueUpdated[i] = format.format(((double) Math.round(Double.parseDouble(pos)*Double.parseDouble(String.valueOf(viewHolder.etValue.getText())))));
i++;
}
}else{
int i = 0;
for(String pos: unitWeightValue ) {
unitWeightValueUpdated[i] = String.valueOf(Double.parseDouble(viewHolder.etValue.getText().toString())* Double.parseDouble(pos) /
Double.parseDouble(unitWeightValueUpdated[i]));
i++;
}
}
}
});
return convertView;
}
private class ViewHolder {
TextView txtItem;
EditText etValue;
public ViewHolder(View view) {
txtItem = view.findViewById(R.id.tvUnitName);
etValue = view.findViewById(R.id.etValue);
}
}
}
unit_row.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:scrollbars="vertical"
android:paddingLeft="5dp"
android:weightSum=".2"
android:orientation="horizontal">
<TextView
android:id="#+id/tvUnitName"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center|left"
android:text="Unit"
android:textSize="16sp"
android:paddingLeft="5dp"
android:layout_weight=".1"
/>
<EditText
android:id="#+id/etValue"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="right"
android:text="100"
android:inputType="numberDecimal"
android:textSize="16sp"
android:paddingRight="15dp"
android:layout_margin="5dp"
android:layout_weight=".1"
/>
</LinearLayout>
activity_main.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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="#+id/unitc_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
Problems:
addTextChangedListener are being called multiple times unnecessarily
Values are not updating properly.
Thanks in advance for the help.
I'm writing a shopping list app that will save data to a Firebase Realtime database and update the screen in real time. As of right now I have it so that when you click the "+ List item" button, it adds a ShoppingListItem to the database with the name "test". It does that correctly, but it isn't updating the screen. I've double checked that the methods are being called, but the screen isn't reflecting the updated data. I have also tried using notifyDataSetChanged() and that hasn't seemed to help either.
This is the code for the ShoppingListFragment:
public class ShoppingListFragment extends Fragment {
private ArrayList<String> listItems = new ArrayList<String>();
private ListView mListView;
private TextView addItemButton;
private LinearLayout ll;
private RecyclerView rv;
private FirebaseRecyclerAdapter<ShoppingListItem, ShoppingListHolder> firebaseRecyclerAdapter;
private DatabaseReference mDatabase;
public ShoppingListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
mDatabase = FirebaseDatabase.getInstance().getReference();
//get reference to user
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
Query query = mDatabase.child("users").child(uid).child("shopping");
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_shopping_list, container, false);
rv = view.findViewById(R.id.shopping_list);
rv.setLayoutManager(new LinearLayoutManager(getContext()));
// find the + List Item button
final TextView addCheckBox = view.findViewById(R.id.add_check_box);
addCheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addNewCheckBox(container);
}
});
FirebaseRecyclerOptions<ShoppingListItem> options = new FirebaseRecyclerOptions.Builder<ShoppingListItem>()
.setQuery(query, ShoppingListItem.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ShoppingListItem, ShoppingListHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull ShoppingListHolder holder, int position, #NonNull ShoppingListItem item) {
holder.setItem(item);
}
#NonNull
#Override
public ShoppingListHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.shopping_list_item, parent, false);
return new ShoppingListHolder(view);
}
};
return view;
}
#Override
public void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
rv.setAdapter(firebaseRecyclerAdapter);
}
#Override
public void onStop() {
super.onStop();
if (firebaseRecyclerAdapter != null) {
firebaseRecyclerAdapter.stopListening();
}
}
public void addNewCheckBox(ViewGroup container) {
String key = mDatabase.child("users").child(getUid()).child("shopping_list").push().getKey();
ShoppingListItem item = new ShoppingListItem("test");
mDatabase.child("users").child(getUid()).child("shopping_list").child(key).setValue(item);
firebaseRecyclerAdapter.notifyDataSetChanged();
}
public int convertToPx(int input) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
int px = (int) (input * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
private class ShoppingListHolder extends RecyclerView.ViewHolder {
private final EditText itemName;
public ShoppingListHolder(View itemView) {
super(itemView);
itemName = itemView.findViewById(R.id.item_name);
}
public void setItem(ShoppingListItem item) {
itemName.setText(item.getItemName());
}
}
private String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
}
and the ShoppingListItem:
public class ShoppingListItem {
private String itemName;
private String type;
private String unit;
private int quantity;
private String location;
public ShoppingListItem() {
}
public ShoppingListItem(String name) {
this.itemName = name;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
}
XML for the shopping list view:
<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:id="#+id/home_fragment_main_layout"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.jggdevelopment.wannacook.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shopping List"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/shopping_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:clipToPadding="false"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/add_check_box"
android:text="+ List item"
android:textSize="16sp"
android:layout_marginStart="40dp"
android:layout_marginTop="16dp"/>
</LinearLayout>
and XML for each line item in the shopping list:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/item_name"
android:layout_weight="1"
android:layout_marginStart="12dp"
android:layout_marginEnd="32dp"
android:inputType="text"
android:background="#android:color/transparent"
/>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/xbutton"
android:layout_marginEnd="12dp"
android:src="#drawable/ic_close_white_24dp"
android:layout_gravity="center_vertical"/>
</LinearLayout>
This is not working because you forgot to set the adapter in the onCreate() method. To solve this, add rv.setAdapter(firebaseRecyclerAdapter);, right before you are returning the view like this:
rv.setAdapter(firebaseRecyclerAdapter);
return view;
And you can remove that line of code from the onStart() method because is not needed there.
If you are interested, I have created a tutorial in which I'm explaining step by step, how to build a Shopping List App using Cloud Firestore and Android.
I have a problem and I can't solve it. I would like to create poll application. I Create 2 classes :
- Poll which contain user's name, the question and an ArrayList of Choice
- Choice contain the choice and its id.
I would like to display on the home page a list of questions (ArrayList) with the differents choices. I managed to display this list but I have a problem with ArrayList of the class Poll because only the first item is display but I want to display all the list of choice.
POLL CLASS
public class Poll{
String question;
String forename;
ArrayList<Choice> list_choices;
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
public ArrayList<Choice> getListChoice() {
return list_choices;
}
public void setListChoice(ArrayList<Choice> list_choices) {
this.list_choices = list_choices;
}
}
CHOICE CLASS
public class Choice {
int id;
String choice;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getChoice() {
return choice;
}
public void setChoice(String choice) {
this.choice = choice;
}
}
Adapter for Poll
public class CustomListAdapter extends BaseAdapter{
ArrayList<Poll> listPolls;
LayoutInflater layoutInflater;
Context context;
public CustomListAdapter(Context context,ArrayList<Poll> listPolls) {
this.listPolls = listPolls;
this.context = context;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return listPolls.size();
}
#Override
public Object getItem(int arg0) {
return listPolls.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
ViewHolder holder;
if (arg1==null)
{
arg1= layoutInflater.inflate(R.layout.row_list, null);
holder = new ViewHolder();
holder.ForenameView = (TextView) arg1.findViewById(R.id.forename);
holder.QuestionView = (TextView) arg1.findViewById(R.id.question);
holder.ChoiceView = (ListView) arg1.findViewById(R.id.choice);
//tagguer notre objet pour pouvoir le récupérer à la prochaine mise à jour graphique.
arg1.setTag(holder);
}
else
{
holder = (ViewHolder) arg1.getTag();
}
holder.ForenameView.setText(listPolls.get(arg0).getForename());
holder.QuestionView.setText(listPolls.get(arg0).getQuestion());
holder.ChoiceView.setAdapter(new CustomListChoiceAdapter(context, listPolls.get(arg0).getListChoice()));
return arg1;
}
static class ViewHolder {
TextView ForenameView;
TextView QuestionView;
ListView ChoiceView;
}
}
Adapter for choice
public class CustomListChoiceAdapter extends BaseAdapter {
ArrayList<Choice> listChoices;
LayoutInflater layoutInflater;
public CustomListChoiceAdapter(Context context,ArrayList<Choice> listChoices) {
this.listChoices = listChoices;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return listChoices.size();
}
#Override
public Object getItem(int arg0) {
return listChoices.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
ViewHolder holder;
if (arg1==null)
{
arg1= layoutInflater.inflate(R.layout.row_list_choice, null);
holder = new ViewHolder();
holder.ChoiceView = (TextView) arg1.findViewById(R.id.choice_text);
//holder.IdView = (TextView) arg1.findViewById(R.id.question);
//tagguer notre objet pour pouvoir le récupérer à la prochaine mise à jour graphique.
arg1.setTag(holder);
}
else
{
holder = (ViewHolder) arg1.getTag();
}
holder.ChoiceView.setText(listChoices.get(arg0).getChoice());
notifyDataSetChanged();
//holder.IdView.setText(listChoices.get(arg0).getId());
return arg1;
}
static class ViewHolder {
TextView ChoiceView;
//TextView IdView;
}
}
XML Home page
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:orientation="vertical"
android:id="#+id/LinearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/customborder"
>
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#000000"
>
</ListView>
</RelativeLayout>
</LinearLayout>
XML Poll List
<?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="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/forename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Medium Text"
android:textColor="#color/blue"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:text="TextView" />
<ListView
android:id="#+id/choice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#000000"
>
</ListView>
</LinearLayout>
</LinearLayout>
XML Choice List
<?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="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/choice_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="Medium Text"
android:textColor="#color/pink"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
</LinearLayout>
Activity which display ArrayList
public class debug extends Activity {
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.debugg);
//Récuperation de ListView crée
lv = (ListView) findViewById(R.id.listView1);
ArrayList<Choice> list_choice = new ArrayList<Choice>();
Choice choix = new Choice();
choix.setChoice("choix 1");
list_choice.add(choix);
choix = new Choice();
choix.setChoice("choix 2");
list_choice.add(choix);
ArrayList<Poll> resultats = new ArrayList<Poll>();
Poll newsData = new Poll();
newsData.setListChoice(list_choice);
newsData.setForename("Paul");
newsData.setQuestion("Question 1");
resultats.add(newsData);
newsData = new Poll();
newsData.setListChoice(list_choice);
newsData.setForename("Laetitia");
newsData.setQuestion("Question 2");
resultats.add(newsData);
lv.setAdapter(new CustomListAdapter(this, resultats));
}
}
Man, the one and origin solution is:
Set your parent ListView item WRAP_CONTENT height. Next, set fixed height of your included ListView item. Then in getView() method set the height of your included ListView the height equals to parent_array_list.size() * child_list_view_item_height. It might be help you.
Code example:
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (listPolls.size() * TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, child_list_view_item_height, displayMetrics)));
holder.ChoiceView.setLayoutParams(params);
i wanted to have a custom listView so I did this:
Created an Activity:
public class PRS_MainList_Act extends ListActivity {
MainListAdapter mladp;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prs__main_list_);
ArrayList<MainMenuItem> menuItems = new ArrayList<MainMenuItem>();
menuItems.add(new MainMenuItem(getResources().getString(R.string.main_list_connectivity), getResources().getString(R.string.main_list_connectivityDesc)));
this.mladp = new MainListAdapter(this, R.layout.man_list_item, R.id.textView1, menuItems);
setListAdapter(mladp);
}
}
Create a class for menu items:
public class MainMenuItem {
private String itemText;
private String itemDescription;
private String itemIMG;
private int itemWeight;
private String itemAssociatedActivity;
public MainMenuItem(String itemText, String itemDescription) {
this.itemText = itemText;
this.itemDescription = itemDescription;
}
public String getItemText() {
return itemText;
}
public void setItemText(String itemText) {
this.itemText = itemText;
}
public String getItemIMG() {
return itemIMG;
}
public void setItemIMG(String itemIMG) {
this.itemIMG = itemIMG;
}
public int getItemWeight() {
return itemWeight;
}
public void setItemWeight(int itemWeight) {
this.itemWeight = itemWeight;
}
public String getItemAssociatedActivity() {
return itemAssociatedActivity;
}
public void setItemAssociatedActivity(String itemAssociatedActivity) {
this.itemAssociatedActivity = itemAssociatedActivity;
}
public String getItemDescription() {
return itemDescription;
}
public void setItemDescription(String itemDescription) {
this.itemDescription = itemDescription;
}
}
Custom array adapter:
public class MainListAdapter extends ArrayAdapter<MainMenuItem> {
ArrayList<MainMenuItem> menuItems;
public MainListAdapter(Context context, int resource,
int textViewResourceId, ArrayList<MainMenuItem> menuItems) {
super(context, resource, textViewResourceId, menuItems);
this.menuItems = menuItems;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.man_list_item, parent);
}
MainMenuItem it = menuItems.get(position);
if (it != null) {
TextView titleTV = (TextView) view.findViewById(R.id.textView1);
TextView descriptionTV = (TextView) view.findViewById(R.id.textView2);
ImageView iconIV = (ImageView)view.findViewById(R.id.imageView1);
if (titleTV != null) {
titleTV.setText(it.getItemText());
}
if(descriptionTV != null){
descriptionTV.setText(it.getItemDescription());
}
if(iconIV != null){
if(it.getItemText().equals(getContext().getResources().getString(R.string.main_list_connectivity)))
iconIV.setImageResource(R.drawable.network_connections);
}
}
return view;
}
}
and here are my activity layout and item layout:
<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"
tools:context=".PRS_MainList_Act" >
<ListView android:id="#android:id/list"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
Item Layout:
<?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="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:src="#drawable/ic_launcher" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
I got this error saying: java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView
Thanks in advance for your help.
You can't use this version of the inflate method:
view = vi.inflate(R.layout.man_list_item, parent);
because this will add the inflated View to the parent, which isn't allowed in a ListView. Instead use this version:
view = vi.inflate(R.layout.man_list_item, parent, false);
which will inflate the view but will not add it to the parent. This version is important because it will provide the proper LayoutParams for your inflated view.