I'm having an issue that I have not been able to solve for a couple weeks now. I have an app that adds two EditTexts and one CheckBox on button click. However, whenever I type some content in the EditTexts, and then scroll down, the content disappears when I scroll back up. I cannot figure out a fix for this. I have found a few other very similar posts, however I have tried all solutions I can find, but none have seemed to do the trick for me yet. Here are a couple similar posts I found:
EditText loses content on scroll in ListView
Saving EditText content in RecyclerView
I've recently done some changes to my program in attempt to fix this as well. I added an ArrayList to my MainActivity and passed it to my adapter. I also made two custom text listeners in which onTextChanged, I add the string to the ArrayList. Then, in onBindViewHolder, I update the position in the text listeners, then set the text to the String in the ArrayList at that position. However, this is giving some strange errors. Now, when I add content to an EditText and scroll down, it adds it to multiple EditTexts, and even changes the content in some of them. I'm not sure how to go about fixing this.
Also, on another note, I have the app enabled for drag and drop and swipe to dismiss. So please take that into account as well if you have a solution. Thank you!
MainActivity
import android.content.ClipData;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ArrayList<ListItems> itemsList;
private RecyclerView mRecyclerView;
private MyRecyclerAdapter adapter;
private List<String> courseStrings = new ArrayList<>();
private List<String> creditStrings = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
courseStrings.add("");
creditStrings.add("");
// Toast variable in order to fix toast queueing issue.
final Toast toast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);
// For the recycler view.
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
itemsList = new ArrayList<>();
adapter = new MyRecyclerAdapter(MainActivity.this, itemsList, courseStrings, creditStrings);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setLayoutManager(linearLayoutManager);
// For the addCourse button.
final Button addCourse = (Button) findViewById(R.id.addCourse);
addCourse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
adapter.createListItem(new ListItems(null, null, false), toast);
toast.setText("New course added");
toast.show();
}
});
final Button clearAll = (Button) findViewById(R.id.clearAll);
clearAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// In order to clear the list.
if (itemsList.size() == 0) {
toast.setText("All courses have already been cleared.");
toast.show();
} else {
adapter.clearAdapter();
toast.setText("All courses have been cleared.");
toast.show();
}
}
});
// For the drag and drop/swipe to dismiss.
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
ItemTouchHelper.LEFT) {
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
final int fromPos = viewHolder.getAdapterPosition();
final int toPos = target.getAdapterPosition();
Collections.swap(itemsList, fromPos, toPos);
adapter.notifyItemMoved(fromPos, toPos);
return true;
}
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemDismiss(viewHolder.getAdapterPosition());
}
});
itemTouchHelper.attachToRecyclerView(mRecyclerView);
} // End of onCreate
} // End of MainActivity
MyRecyclerAdapter
import android.app.Activity;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.view.LayoutInflater;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.CustomRowViewHolder> {
private ArrayList<ListItems> itemsList;
private Context mContext;
private List<String> courseStrings;
private List<String> creditStrings;
public MyRecyclerAdapter(Context context, ArrayList<ListItems> itemsList, List<String> courseStrings, List<String> creditStrings){
this.itemsList = itemsList;
this.mContext = context;
this.courseStrings = courseStrings;
this.creditStrings = creditStrings;
}
#Override
public MyRecyclerAdapter.CustomRowViewHolder onCreateViewHolder(final ViewGroup viewGroup, int position) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.new_course_row, null);
final CustomRowViewHolder holder = new CustomRowViewHolder(v, new CoursesCustomTextListener(), new CreditsCustomTextListener());
holder.creditsText.setInputType(InputType.TYPE_CLASS_NUMBER);
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(holder.checkBox.isChecked()) {
holder.courseText.setEnabled(false);
holder.courseText.setFocusable(false);
holder.courseText.setInputType(InputType.TYPE_NULL);
holder.creditsText.setEnabled(false);
holder.creditsText.setFocusable(false);
holder.creditsText.setInputType(InputType.TYPE_NULL);
} else {
holder.courseText.setEnabled(true);
holder.courseText.setFocusable(true);
holder.courseText.setFocusableInTouchMode(true);
holder.courseText.setInputType(InputType.TYPE_CLASS_TEXT);
holder.creditsText.setEnabled(true);
holder.creditsText.setFocusable(true);
holder.creditsText.setFocusableInTouchMode(true);
holder.creditsText.setInputType(InputType.TYPE_CLASS_NUMBER);
} // End if else
}
});
return holder;
} // End of onCreateViewHolder
#Override
public void onBindViewHolder(CustomRowViewHolder holder, final int position) {
ListItems listItem = itemsList.get(position);
int focusedItem = 0;
holder.itemView.setSelected(focusedItem == position);
holder.getLayoutPosition();
holder.creditsCustomTextListener.updatePosition(position);
holder.creditsCustomTextListener.updatePosition(position);
holder.courseText.setText(courseStrings.get(position));
holder.creditsText.setText(creditStrings.get(position));
// Set listener to check box.
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
itemsList.get(position).setIsComplete(b);
}
});
holder.checkBox.setChecked( itemsList.get(position).getIsComplete());
} // End of onBindViewHolder
public void clearAdapter() {
itemsList.clear();
notifyDataSetChanged();
} // End of clearAdapter
public int getItemCount() {
return(null != itemsList ? itemsList.size() : 0);
} // End of getItemCount
public void onItemDismiss(int position) {
itemsList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, itemsList.size());
} // End of onItemDismiss
public void createListItem(ListItems listItem, Toast toast) {
itemsList.add(listItem);
int position = itemsList.indexOf(listItem);
notifyItemInserted(position);
} // End of createListItem
///////////////////////////////////// CustomRowViewHolder /////////////////////////////////////
public static class CustomRowViewHolder extends RecyclerView.ViewHolder {
public EditText courseText;
public EditText creditsText;
public CheckBox checkBox;
public RelativeLayout relativeLayout;
public CoursesCustomTextListener coursesCustomTextListener;
public CreditsCustomTextListener creditsCustomTextListener;
public CustomRowViewHolder(View view, CoursesCustomTextListener coursesCustomTextListener, CreditsCustomTextListener creditsCustomTextListener) {
super(view);
this.coursesCustomTextListener = coursesCustomTextListener;
this.creditsCustomTextListener = creditsCustomTextListener;
this.courseText = (EditText) view.findViewById(R.id.course);
this.creditsText = (EditText) view.findViewById(R.id.credits);
this.checkBox = (CheckBox) view.findViewById(R.id.complete);
this.relativeLayout = (RelativeLayout) view.findViewById(R.id.relLayout);
this.courseText.addTextChangedListener(coursesCustomTextListener);
this.creditsText.addTextChangedListener(creditsCustomTextListener);
}
}
////////////////////////////////// CoursesCustomTextListener //////////////////////////////////
private class CoursesCustomTextListener implements TextWatcher {
private int position;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// No operation to perform.
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
courseStrings.add(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
// No operation to perform.
}
}
////////////////////////////////// CreditsCustomTextListener //////////////////////////////////
private class CreditsCustomTextListener implements TextWatcher {
private int position;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// No operation to perform.
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
creditStrings.add(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
// No operation to perform.
}
}
} // End of MyRecyclerAdapter
ListItems
import java.util.ArrayList;
public class ListItems {
private String course;
private String credits;
private Boolean complete;
public ListItems(String mCourse, String mCredits, Boolean mComplete) {
course = mCourse;
credits = mCredits;
complete = mComplete;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public String getCredits() {
return credits;
}
public void setCredits(String credits) {
this.credits = credits;
}
public Boolean getIsComplete() {
return complete;
}
public void setIsComplete(Boolean complete) {
this.complete = complete;
}
} // End of ListItems
new_course_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/relLayout"
android:layout_margin="5dp">
<EditText
android:layout_width="130dp"
android:layout_height="wrap_content"
android:id="#+id/course"
android:hint="Enter Course ID"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:textSize="16sp"
android:maxLines="1" />
<EditText
android:layout_width="115dp"
android:layout_height="wrap_content"
android:id="#+id/credits"
android:hint="Enter Credits"
android:layout_alignBottom="#+id/course"
android:textSize="16sp"
android:layout_toRightOf="#+id/course"
android:maxLines="1" />
<CheckBox
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Check if complete"
android:id="#+id/complete"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignBottom="#+id/course"
android:textSize="13sp"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
</RelativeLayout>
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:paddingRight="10dp"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:id="#+id/rl"
tools:context=".MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Course"
android:id="#+id/addCourse"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:textColor="#FFF"
android:background="#drawable/my_button"
android:textSize="18dp"
android:paddingRight="5dp"
android:paddingLeft="5dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear All"
android:id="#+id/clearAll"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:textColor="#FFF"
android:background="#drawable/my_button"
android:textSize="18dp"
android:paddingRight="5dp"
android:paddingLeft="5dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"/>
<android.support.v7.widget.RecyclerView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/recycler_view"
android:layout_below="#+id/addCourse"
android:layout_marginTop="10dp"
/>
</RelativeLayout>
Thank you in advance for any help! I could REALLY use a solution!
EDIT: I've noticed now that, say I enter "aaaaaaa" in the first EditText, then it will add "a" to an EditText further down the list, then "aa" to the EditText after that one, then "aaa", "aaaa", until it reaches "aaaaaaa". Then there will be a few empty EditText's, and then it will start it over again. Here is a visual:
EDIT x2: Haven't worked on this in a while, and haven't been getting any answers. Even got the "Tumbleweed" badge for this post! Anyone have any ideas?
Though I am not quite sure but I believe this is happening because recycler view regenerates its positons . For your custom edit text you are adding the string ` #Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
courseStrings.add(s.toString());
}
for both edit texts.
In recyler view you have implemented this.courseText.addTextChangedListener(coursesCustomTextListener);
so everytime you scroll the onBind Method is called and as the position changes this must be getting called too. Hence it must be regenerating . I request you to first try
holder.courseText.setTag(position);
in onBindViewHolder().
Try it for both texts individually.If it does work then try
holder.view.setTag(position);
Related
I am trying to make a program where I list the file names in a recyclerview. Using a button inside the row, the application should delete the item via a path which is stored in an array that includes the file path. The application should also display the file path if the card itself is clicked in a toast message.
So far I am able to do this, however I can only delete one file at a time when the application is active. The problem arises when I try to delete multiple files. The items are deleted from the recyclerview and everything looks normal, but if the application is closed then the files that I attempted to delete after the first one show up again, indicating that they were not deleted.
My code:
JAVA CLASSES
FileView.java (this is the main activity)
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
public class FileView extends AppCompatActivity {
private RecyclerView fileRecyclerView;
private RowAdapter fileAdapter;
private RecyclerView.LayoutManager fileLayoutManager;
private ArrayList<RowItem> rowItem;
File[] fileList;
String filePath = "";
String fileData = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_view);
filePath = "PDF_files";
File file = new File(getExternalFilesDir(filePath).toString());
fileList = file.listFiles();
createRows();
buildRecyclerView();
}
public void createRows(){
rowItem = new ArrayList<>();
for (int i = 0; i < fileList.length; i++) {
rowItem.add(new RowItem(R.drawable.ic_book,(fileList[i].getName().replace("__", " ").replace('_','\n').replace('-','/').replace(".pdf",""))));
}
}
public void removeItem(int position) {
rowItem.remove(position);
fileAdapter.notifyItemRemoved(position);
}
public void buildRecyclerView() {
fileRecyclerView = findViewById(R.id.recyclerView);
fileRecyclerView.setHasFixedSize(true);
fileLayoutManager = new LinearLayoutManager(this);
fileAdapter = new RowAdapter(rowItem);
fileRecyclerView.setLayoutManager(fileLayoutManager);
fileRecyclerView.setAdapter(fileAdapter);
fileAdapter.setOnItemClickListener(new RowAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
fileData = fileList[position].toString();
Toast.makeText(FileView.this,"Clicked: " + fileData , Toast.LENGTH_SHORT).show();
}
#Override
public void onDeleteClick(int position) {
removeItem(position);
File deletePath = fileList[position];
deletePath.delete();
if(deletePath.exists()){
getApplicationContext().deleteFile(deletePath.getName());
}
}
});
}
}
RowAdapter.java (this is the adapter class)
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RowAdapter extends RecyclerView.Adapter<RowAdapter.RowViewHolder> {
private ArrayList<RowItem> mRowList;
private OnItemClickListener mListener;
public interface OnItemClickListener{
void onItemClick(int position);
void onDeleteClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public static class RowViewHolder extends RecyclerView.ViewHolder{
public ImageView rowImageView;
public TextView rowTextView;
public ImageView rowDeleteImage;
public RowViewHolder(#NonNull View itemView, OnItemClickListener listener) {
super(itemView);
rowImageView = itemView.findViewById(R.id.fileImage);
rowTextView = itemView.findViewById(R.id.fileName);
rowDeleteImage = itemView.findViewById(R.id.deleteFile);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(position);
}
}
}
});
rowDeleteImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onDeleteClick(position);
}
}
}
});
}
}
public RowAdapter(ArrayList<RowItem> rowList){
mRowList = rowList;
}
#NonNull
#Override
public RowViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
RowViewHolder rvh = new RowViewHolder(v, mListener);
return rvh;
}
#Override
public void onBindViewHolder(#NonNull RowViewHolder holder, int position) {
RowItem currentItem = mRowList.get(position);
holder.rowImageView.setImageResource(currentItem.getImageResource());
holder.rowTextView.setText(currentItem.getFileName());
}
#Override
public int getItemCount() {
return mRowList.size();
}
}
RowItem.java (getters for image and filename)
public class RowItem {
private int imageResource;
private String fileName;
public RowItem(int img, String stringInput) {
this.imageResource = img;
this.fileName = stringInput;
}
public int getImageResource() {
return imageResource;
}
public String getFileName() {
return fileName;
}
}
XML FILES
activity_file_view.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:orientation="vertical"
tools:context="com.loopbreakr.firstpdf.FileView">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
android:scrollbars="vertical"
android:background="#color/cardview_shadow_start_color"
/>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_marginBottom="4dp"
app:cardCornerRadius="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp">
<ImageView
android:id="#+id/fileImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="2dp"/>
<TextView
android:id="#+id/fileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="55dp"
android:layout_marginTop="5dp"
android:text="File Name"
android:textColor="#color/black"
android:textSize="20sp" />
<ImageView
android:id="#+id/deleteFile"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_margin="5dp"
android:padding="2dp"
android:src="#drawable/ic_delete" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
EDIT
I tried to change the array to an arraylist as suggested, however I think I must have done so incorrectly as this results in a crash.
FileView.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FileView extends AppCompatActivity {
private RecyclerView fileRecyclerView;
private RowAdapter fileAdapter;
private RecyclerView.LayoutManager fileLayoutManager;
private ArrayList<RowItem> rowItem;
List<File> fileList;
String filePath = "";
String fileData = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_view);
filePath = "PDF_files";
File file = new File(getExternalFilesDir(filePath).toString());
fileList = Arrays.asList(file.listFiles());
createRows();
buildRecyclerView();
}
public void createRows(){
rowItem = new ArrayList<>();
for (int i = 0; i < fileList.size(); i++) {
rowItem.add(new RowItem(R.drawable.ic_book,(fileList.get(i).getName().replace("__", " ").replace('_','\n').replace('-','/').replace(".pdf",""))));
}
}
public void removeItem(int position) {
rowItem.remove(position);
fileAdapter.notifyItemRemoved(position);
}
#Override
public void recreate() {
super.recreate();
}
public void buildRecyclerView() {
fileRecyclerView = findViewById(R.id.recyclerView);
fileRecyclerView.setHasFixedSize(true);
fileLayoutManager = new LinearLayoutManager(this);
fileAdapter = new RowAdapter(rowItem);
fileRecyclerView.setLayoutManager(fileLayoutManager);
fileRecyclerView.setAdapter(fileAdapter);
fileAdapter.setOnItemClickListener(new RowAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
fileData = fileList.get(position).toString();
Toast.makeText(FileView.this,"Clicked: " + fileData , Toast.LENGTH_SHORT).show();
}
#Override
public void onDeleteClick(int position) {
removeItem(position);
File deletePath = fileList.get(position);
deletePath.delete();
if(deletePath.exists()){
getApplicationContext().deleteFile(deletePath.getName());
}
fileList.remove(position);
}
});
}
}
When you delete a record, the table widget (the stuff you see on your device) is updated and the row is removed. However, your fileList array is not updated; it still has the Path representing that deleted file (you deleted the file, sure, but any objects that capture the notion of the path of that file are still around, of course).
When you delete a file, you need to also fix the fileList array. Given that arrays cannot grow or shrink, this is probably a lot simpler if you use a List<File> instead of a File[].
You make it yourself difficult as you keep two lists.
rowItems and fileList.
In RowItems you have only a String variable fileName.
Add a variable String filePath and use it instead of the file list array.
Basically on clicking a button a dialog box opens from which I am capturing information. Once I click on "Done" option present in the Dialog box, I want a new card to be created comprising of that information. I have implemented recycler view for achieving the above but for some reason it is not working. Could someone tell me what's wrong?
Here's the code of my Adapter
package com.example.android.teleconsultation_doctor;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class AdapterManageSlots extends RecyclerView.Adapter<AdapterManageSlots.ManageSlotsViewHolder> {
private ArrayList<CardViewManageSlots> mManageSlots;
public static class ManageSlotsViewHolder extends RecyclerView.ViewHolder{
public TextView mSlots, mTiming;
public ManageSlotsViewHolder(#NonNull View itemView) {
super(itemView);
mTiming = itemView.findViewById(R.id.textViewTimingValue);
mSlots = itemView.findViewById(R.id.textViewSlotValue);
}
}
public AdapterManageSlots(ArrayList<CardViewManageSlots> manageSlots){
mManageSlots = manageSlots;
}
#NonNull
#Override
public ManageSlotsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cardview_manage_slots, viewGroup, false);
ManageSlotsViewHolder evh = new ManageSlotsViewHolder(v);
return evh;
}
#Override
public void onBindViewHolder(#NonNull ManageSlotsViewHolder manageSlotsViewHolder, int i) {
CardViewManageSlots currentItem = mManageSlots.get(i);
manageSlotsViewHolder.mSlots.setText(currentItem.getSlot());
manageSlotsViewHolder.mTiming.setText(currentItem.getTiming());
}
#Override
public int getItemCount() {
return mManageSlots.size();
}
}
Here is the JAVA code of the activity
package com.example.android.teleconsultation_doctor;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.content.DialogInterface;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
public class ManageSlots extends AppCompatActivity implements DatePickerDialog.OnDateSetListener, AdapterView.OnItemSelectedListener {
ImageView imageViewCalender;
TextView textViewDateValue;
String date, spinnerSlotValue, spinnerEndTimeValue, spinnerStartTimeValue;
Button buttonAddSlot;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_slots);
ArrayList<CardViewManageSlots> slotDetails = new ArrayList<>();
imageViewCalender = findViewById(R.id.imageViewCalander);
textViewDateValue = findViewById(R.id.textViewDateValue);
buttonAddSlot = findViewById(R.id.buttonAddSlot);
imageViewCalender.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDatePickerDialog();
}
});
buttonAddSlot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(ManageSlots.this);
View mView = getLayoutInflater().inflate(R.layout.dialog_manage_slots, null);
Spinner mSpinnerSlots = mView.findViewById(R.id.spinnerSlots);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(ManageSlots.this, android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.slot_names));
adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
mSpinnerSlots.setAdapter(adapter);
spinnerSlotValue = mSpinnerSlots.getSelectedItem().toString();
Spinner mSpinnerStartTime = mView.findViewById(R.id.spinnerStartTime);
ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(ManageSlots.this, android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.time));
adapter1.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
mSpinnerStartTime.setAdapter(adapter1);
spinnerStartTimeValue = mSpinnerStartTime.getSelectedItem().toString();
Spinner mSpinnerEndTime = mView.findViewById(R.id.spinnerEndTime);
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(ManageSlots.this, android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.time));
adapter2.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
mSpinnerEndTime.setAdapter(adapter2);
spinnerEndTimeValue = mSpinnerEndTime.getSelectedItem().toString();
mBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Toast.makeText(ManageSlots.this, "Slot Created!" + spinnerSlotValue + spinnerEndTimeValue + spinnerStartTimeValue, Toast.LENGTH_LONG).show();
dialogInterface.dismiss();
}
});
mBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
mBuilder.setView(mView);
AlertDialog dialog = mBuilder.create();
dialog.show();
}
});
String finalTime = spinnerStartTimeValue + "-" + spinnerEndTimeValue;
Toast.makeText(this, finalTime, Toast.LENGTH_SHORT).show();
slotDetails.add(new CardViewManageSlots(spinnerSlotValue,finalTime));
//slotDetails.add(new CardViewManageSlots("Morning","diwwodmw"));
mRecyclerView = findViewById(R.id.recyclerViewSlots);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new AdapterManageSlots(slotDetails);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
private void showDatePickerDialog() {
DatePickerDialog datePickerDialog = new DatePickerDialog(
this,
this,
Calendar.getInstance().get(Calendar.YEAR),
Calendar.getInstance().get(Calendar.MONTH),
Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
);
datePickerDialog.show();
}
#Override
public void onDateSet(DatePicker datePicker, int i, int i1, int i2) {
int i3=i1;
i3=i3+1;
date = i2 + "/" + i3 + "/" + i;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR,i);
cal.set(Calendar.MONTH,i1);
cal.set(Calendar.DAY_OF_MONTH,i2);
String selectedDate = DateFormat.getDateInstance().format(cal.getTime());
textViewDateValue.setText(selectedDate);
}
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
Here is the XML code of the activity
<?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=".ManageSlots">
<include
layout="#layout/toolbar_layout"
android:id="#+id/mytoolbar"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Date:"
android:id="#+id/textViewSelectDate"
android:layout_below="#id/mytoolbar"
android:layout_margin="10dp"
android:textSize="20dp"
android:textColor="#000"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageViewCalander"
android:src="#drawable/round_today_black_18dp_2x"
android:layout_toRightOf="#id/textViewSelectDate"
android:layout_below="#id/mytoolbar"
android:layout_marginTop="5dp"
android:clickable="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textViewDateValue"
android:layout_below="#id/imageViewCalander"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:textSize="20dp"
android:text="Aug 21, 2020"
android:textColor="#000"
/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/textViewDateValue"
android:id="#+id/recyclerViewSlots"
android:padding="4dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/buttonAddSlot"
android:text="Add Slot"
android:layout_alignParentBottom="true"
android:layout_margin="10dp"
android:background="#color/colorPrimaryDark"
android:textColor="#fff"/>
</RelativeLayout>
If I understand it correctly, you want something like this:
mBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
spinnerSlotValue = mSpinnerSlots.getSelectedItem().toString();
spinnerStartTimeValue = mSpinnerStartTime.getSelectedItem().toString();
spinnerEndTimeValue = mSpinnerEndTime.getSelectedItem().toString();
String finalTime = spinnerStartTimeValue + "-" + spinnerEndTimeValue;
slotDetails.add(new CardViewManageSlots(spinnerSlotValue,finalTime));
mAdapter.notifyDataSetChanged();
dialogInterface.dismiss();
}
});
I've been trying to implement a simple scrollable list that gets its data from Firebase Database using RecyclerView on an activity called MyOrganisedEventsActivity. Problem is, when my main activity starts the MyOrganisedEventsActivity, there is no call made to the method onCreateViewHolder, and thus the RecyclerView is empty.
However, after waiting a moment and then locking and unlocking my phone, a call is made to onCreateViewHolder and the list items start appearing on the RecyclerView. Is there anyway to force the call when the activity is first started? Or is there something wrong with my code and how can I fix it?
Here's my code so far:
MyOrganisedEventsActivity.java:
package com.llawl.tristonpang.intheloop;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MyOrganisedEventsActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private OrganisedEventsAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<EventInfo> mEventsDataset;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_organised_events);
mRecyclerView = (RecyclerView) findViewById(R.id.org_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mEventsDataset = new ArrayList<>();
// specify an adapter (see also next example)
mAdapter = new OrganisedEventsAdapter(mEventsDataset);
mRecyclerView.setAdapter(mAdapter);
prepareEventsData();
}
private void prepareEventsData() {
final String currentUser = FirebaseAuth.getInstance().getCurrentUser().getEmail();
Log.d("InTheLoop", "prepareEventsData(), currentUser = " + currentUser);
FirebaseDatabase.getInstance().getReference().child("events_info").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
//EventInfo event = snapshot.getValue(EventInfo.class);
HashMap<String,String> data = (HashMap) snapshot.getValue();
//Log.d("InTheLoop", "Event name: " + event.getName());
//if (event.getOrganiser().equals(currentUser)) {
if (data.get("organiser").equals(currentUser)) {
Log.d("InTheLoop", "Adding event: " + data.get("name"));
EventInfo event = new EventInfo(data.get("name"), data.get("date"), data.get("time"), data.get("venue"),
data.get("desc"), data.get("imageName"), data.get("organiser"));
mEventsDataset.add(event);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mAdapter.notifyDataSetChanged();
}
}
OrganisedEventsAdapter.java:
package com.llawl.tristonpang.intheloop;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class OrganisedEventsAdapter extends RecyclerView.Adapter<OrganisedEventsAdapter.ViewHolder> {
private List<EventInfo> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mName;
public TextView mVenue;
public TextView mDate;
public ViewHolder(View v) {
super(v);
mName = v.findViewById(R.id.org_row_name);
mVenue = v.findViewById(R.id.org_row_venue);
mDate = v.findViewById(R.id.org_row_date);
}
}
public OrganisedEventsAdapter(List<EventInfo> dataset) {
mDataset = dataset;
}
// Create new views (invoked by the layout manager)
#Override
public OrganisedEventsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.organised_event_row, parent, false);
Log.d("InTheLoop", "Adapter, onCreateViewHolder");
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
EventInfo event = mDataset.get(position);
Log.d("InTheLoop", "Adapter, Event name: " + event.getName());
holder.mName.setText(event.getName());
holder.mVenue.setText(event.getVenue());
holder.mDate.setText(event.getDate());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
EventInfo.java:
package com.llawl.tristonpang.intheloop;
public class EventInfo {
private String mName;
private String mDate;
private String mTime;
private String mVenue;
private String mDesc;
private String mImageName;
private String mOrganiser;
public EventInfo() {
}
public EventInfo(String name, String date, String time, String venue, String desc, String imageName, String organiser) {
mName = name;
mDate = date;
mTime = time;
mVenue = venue;
mDesc = desc;
mImageName = imageName;
mOrganiser = organiser;
}
public String getName() {
return mName;
}
public String getDate() {
return mDate;
}
public String getTime() {
return mTime;
}
public String getVenue() {
return mVenue;
}
public String getDesc() {
return mDesc;
}
public String getImageName() {
return mImageName;
}
public String getOrganiser() {
return mOrganiser;
}
}
organised_event_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/single_event_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:paddingBottom="#dimen/row_padding_vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/row_padding_vertical">
<TextView
android:id="#+id/org_row_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="name"
android:textColor="#color/black"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/org_row_venue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/org_row_name"
android:text="venue" />
<TextView
android:id="#+id/org_row_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="date"
android:textColor="#color/black" />
</RelativeLayout>
activity_my_organised_events.xml:
<?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:layout_height="match_parent"
tools:context=".MyOrganisedEventsActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/org_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
Any help is much appreciated! Thanks!
Move mAdapter.notifyDataSetChanged(); inside onDataChange(DataSnapshot dataSnapshot) . You have missed the nature of asynchronous call.
FirebaseDatabase.getInstance().getReference().child("events_info").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
// Build data here
}
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
call mAdapter.notifyDataSetChanged(); after you add data in List in for loop in onDataChange()
so basically add data in your data structure and then notify adapter to update itself with new data.
this is a small application which asks some questions and then it will show answers. When we finish answering all the questions, new activity appears and shows us the all the answers except the last one. I searched this problem and saw answers but none of them is working in my case. Thanks for any kind of help.
This is my code:
XML code for the main layout.
<?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"
tools:context="com.itrio.iqtest.Result_QA"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Answers"
android:textSize="22sp"
android:textStyle="bold"
android:layout_margin="20dp"/>
<ListView
android:id="#+id/result_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
Another XML custom view.
<?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"
android:layout_margin="10dp"
android:padding="10dp">
<TextView
android:id="#+id/question_result"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="18sp"
android:textStyle="bold">
</TextView>
<View
android:layout_width="match_parent"
android:layout_height="10dp"/>
<TextView
android:textStyle="italic"
android:id="#+id/answer_result"
android:layout_width="fill_parent"
android:textSize="18sp"
android:layout_marginBottom="10dp"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
Here's the code for questions:
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
public class Genius extends AppCompatActivity {
private TextView question_view;
private Button mNext;
int currentQ = 0;
RadioGroup genius_rg;
RadioButton op1, op2, op3, op4,checked;
private int score;
int turns=0;
boolean check= false, shuffle = true;
String[] questions = new String[8];
String[] answers = new String[8];
//Keys
private static final String Question_Index_key = "Index value of Questions";
private static final String Checked_Radio = "Selected radio Button";
private static final String Is_Radio_Checked = "ISC";
private static final String Do_Not_Shuffle_Again = "Dont' shuffle";
public static final String Result_Questions = "questions to display at result activity";
public static final String Result_Answers = "answers to display at result activity";
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(Question_Index_key,currentQ);
outState.putInt(Checked_Radio,genius_rg.getCheckedRadioButtonId());
outState.putBoolean(Is_Radio_Checked,check);
outState.putBoolean(Do_Not_Shuffle_Again, shuffle);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Dialog alert_exit = new QuizExitAlert(Genius.this);
alert_exit.show();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Changes 'back' button action
if (keyCode == KeyEvent.KEYCODE_BACK) {
Dialog alert_exit = new QuizExitAlert(Genius.this);
alert_exit.show();
}
return true;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_genius);
if (savedInstanceState != null) {
currentQ = savedInstanceState.getInt(Question_Index_key);
if (savedInstanceState.getBoolean(Is_Radio_Checked)) {
checked = (RadioButton) findViewById(savedInstanceState.getInt(Checked_Radio));
checked.setChecked(true);
}
shuffle = savedInstanceState.getBoolean(Do_Not_Shuffle_Again);
}
question_view = (TextView) findViewById(R.id.question_genius);
genius_rg = (RadioGroup) findViewById(R.id.radio_genius);
op1 = (RadioButton) findViewById(R.id.g_op1);
op2 = (RadioButton) findViewById(R.id.g_op2);
op3 = (RadioButton) findViewById(R.id.g_op3);
op4 = (RadioButton) findViewById(R.id.g_op4);
Collections.shuffle(bank);
question_view.setText(bank.get(currentQ).getQ());
op1.setText(bank.get(currentQ).getOp1());
op2.setText(bank.get(currentQ).getOp2());
op3.setText(bank.get(currentQ).getOp3());
op4.setText(bank.get(currentQ).getOp4());
mNext = (Button) findViewById(R.id.next_genius);
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
turns++;
if (turns >= 8) {
new AlertDialog.Builder(Genius.this)
.setTitle("Done!!!")
.setMessage("You have answered all the questions.")
.setPositiveButton("Submit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent result = new Intent(Genius.this,Result_QA.class);
result.putExtra(Result_Questions, questions);
result.putExtra(Result_Answers, answers);
startActivity(result);
}
}).show();
}else {
if (op1.isChecked() || op2.isChecked() || op3.isChecked() || op4.isChecked()) {
checked = (RadioButton) findViewById(genius_rg.getCheckedRadioButtonId());
if (bank.get(currentQ).getAns() == checked.getText()) {
score += 10;
}
questions[currentQ] = bank.get(currentQ).getQ();
answers[currentQ] = bank.get(currentQ).getAns();
genius_rg.clearCheck();
currentQ++;
question_view.setText(bank.get(currentQ).getQ());
op1.setText(bank.get(currentQ).getOp1());
op2.setText(bank.get(currentQ).getOp2());
op3.setText(bank.get(currentQ).getOp3());
op4.setText(bank.get(currentQ).getOp4());
} else {
Toast.makeText(Genius.this, "Select an option to proceed", Toast.LENGTH_SHORT).show();
}
}
}
});
}
}
Here's the code for LisView Activity:
import android.os.Bundle;
import android.app.Activity;
import android.widget.ListView;
public class Result_QA extends Activity {
ListView result;
ReslutListViewAdapter reslutListViewAdapter;
String[] ques, ans;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result__q);
Bundle b= getIntent().getExtras();
ques = b.getStringArray(new Genius().Result_Questions);
ans = b.getStringArray(new Genius().Result_Answers);
result = (ListView) findViewById(R.id.result_view);
reslutListViewAdapter = new ReslutListViewAdapter(this, ques, ans);
System.out.println("adapter => "+reslutListViewAdapter.getCount());
result.setAdapter(reslutListViewAdapter);
}
}
Code for ListViewAdapter class:
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ReslutListViewAdapter extends BaseAdapter {
Activity context;
String[] questions;
String[] answers;
public ReslutListViewAdapter(Activity con, String[] ques, String[] ans){
super();
context = con;
questions = ques;
answers = ans;
}
#Override
public int getCount() {
return questions.length;
}
private class ViewHolder {
TextView mQ;
TextView mA;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null)
{
convertView = inflater.inflate(R.layout.result_listadapter, null);
holder = new ViewHolder();
holder.mQ = (TextView) convertView.findViewById(R.id.question_result);
holder.mA = (TextView) convertView.findViewById(R.id.answer_result);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.mQ.setText(questions[position]);
holder.mA.setText(answers[position]);
return convertView;
}
}
First of all listview is old one Recyclerview had came, which makes our work easier and lot more improvements have been done in RecyclerView to make developer work easier.
Coming to this issue, ListView doesn't support wrap_content. So change the height and width of ListView to match_parent. Then in adapter xml file the parent layout height should be wrap_content, but you have mentioned it as match_parent, so change that also to wrap_content. Hopefully, this should solve your problem. If the above solution didn't work, then try by removing the padding and margin in the adapter XML layout(from the parent layout in result_listadapter.xml file).
FYI fill_parent is deprecated and we are supposed to use match_parent instead of that. So avoid using the fill_parent.
Hope this helps:)
I am creating an app in android studios that requires the user to select a child item from an expandable listview on one activity and for it to be displayed on another activity. I'm new to java and android studios and still dont understand how to do this really. If anyone has any sample code or can help that would be great, thanks!
You should use the setOnChildClickListener method from the ExpandableListView class to create a ClickListener for the list elements and then use a Intent to open the new activity. The call to set the listener should be set after you've set the adapter for the ListView.
Here there's a tutorial for using a ExpandableListView and it shows how to set a ClickListener for the elements.
And here there's the Android developer's documentation which shows how to create and open a new Activity from a button's click.
**You should use the setOnChildClickListener method from the ExpandableListView class to create a ClickListener for the list elements and then use a Intent to open the new activity. The call to set the listener should be set after you've set the adapter for the ListView and create the xml file for child and parent.child will be Expandable TextView **
**layout file**
<?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:id="#+id/activity_main"
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.example.elite_android.explistview1.MainActivity">
<RelativeLayout
android:id="#+id/main_number_picker_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="17dp">
<NumberPicker
android:id="#+id/main_number_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Next" />
<TextView
android:id="#+id/main_txt_patient_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#id/main_number_picker"
android:text="Select number of patient"
android:textColor="#color/colorAccent"
android:layout_marginLeft="80dp"/>
</RelativeLayout>
<ExpandableListView
android:id="#+id/exp_Listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/main_number_picker_layout">
</ExpandableListView>
</RelativeLayout>
**Main Activity.java file**
package com.example.elite_android.explistview1;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.view.View.OnFocusChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ListView;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.NumberPicker;
public class MainActivity extends AppCompatActivity {
ExpandableListView expandableListView;
private MyAdapter mAdapter;
ExpandableListView expand;
NumberPicker numberPicker;
private List<String> headerItems;
private ArrayList childDetails;
private HashMap<String, List<String>> childList;
private Context ctx;
EditText editText1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get reference to the EditText
editText1 = (EditText) findViewById(R.id.child_item);
// //set the onFocusChange listener
// // editText1.setOnFocusChangeListener(editText1.getOnFocusChangeListener());
//
//// //get reference to EditText
//// editText2 = (EditText) findViewById(R.id.sequence);
//// // set the on focusChange listner
//// editText2.setOnFocusChangeListener(editText2.getOnFocusChangeListener());
//
// //Generate list View from ArrayList;
//
//
// EditText editText = (EditText) findViewById(R.id.child_item);
// editText.requestFocus();
// InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
//
//
//// editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
// // #Override
// // public void onFocusChange(View v, boolean hasFocus) {
// // //editText.setOnFocusChangeListener();
// // return;
// // }
// //});
//
String[] numbers = new String[10];
for (int count = 0; count < 10; count++)
numbers[count] = String.valueOf(count);
numberPicker = (NumberPicker) findViewById(R.id.main_number_picker);
numberPicker.setMaxValue(numbers.length);
numberPicker.setMinValue(1);
numberPicker.setDisplayedValues(numbers);
numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
generateListItems(newVal);
loadRecycleView();
}
});
}
private void generateListItems(int childCount) {
if (headerItems != null)
headerItems.clear();
else
headerItems = new ArrayList<>();
if (childList != null)
childList.clear();
else
childList = new HashMap();
if (childDetails == null) {
childDetails = new ArrayList();
childDetails.add("Name");
childDetails.add("Age");
childDetails.add("Gender");
}
// Put header items
for (int count = 0; count < childCount; count++) {
headerItems.add(" Parent " + count);
childList.put(headerItems.get(count), childDetails);
}
}
private void loadRecycleView() {
if (expandableListView == null) {
expandableListView = (ExpandableListView) findViewById(R.id.exp_Listview);
mAdapter = new MyAdapter(this, headerItems, childList);
expandableListView.setAdapter(mAdapter);
} else {
expandableListView.invalidate();
mAdapter.setHeaderData(headerItems);
mAdapter.setListData(childList);
mAdapter.notifyDataSetChanged();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
}
**Adapter class.java**
package com.example.elite_android.explistview1;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.widget.EditText;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.view.View.OnFocusChangeListener;
/**
* Created by ELITE-ANDROID on 28-02-2017.
*/
// this is provides all needs methods implementing an Expandable List VIew
public class MyAdapter extends BaseExpandableListAdapter {
// We need some Variables here so therer are some Variables here
private List<String> header_titles; // This is for Representing the HeadLine(Array list)
private HashMap<String, List<String>> child_titles; // defin the HashMap for the child item how to Represent the Parent Handing so Hash Map, need some Variables
private Context ctx;
private NumberPicker numberPicker;
EditText editText;
View view;
private static LayoutInflater inflater = null;
//for initalized for all Variables we need some Constructor
public MyAdapter(Context context, List<String> header_titles, HashMap<String, List<String>> child_titles) {
super();
this.ctx = context;
this.child_titles = child_titles;
this.header_titles = header_titles;
}
public void refreshHeader_titles(List<String> events) {
this.header_titles.clear();
this.header_titles.addAll(header_titles);
notifyDataSetChanged();
}
;
#Override
// From this Override method How to Return how many elements are the Group count like parent
public int getGroupCount() {
return header_titles.size();
}
#Override
//here the number of child items are in each heading. There are three Heading - PAtien Name ,Age, Gender
public int getChildrenCount(int groupPosition) {
// Log.d("xxx", )
return child_titles.get(header_titles.get(groupPosition)).size(); //how to Return the size of HashMap
}
#Override
public Object getGroup(int groupPosition) {
return header_titles.get(groupPosition);
}
#Override
// here how to retuen child items on the particular headings and Positions.
public Object getChild(int groupPosition, int childPosition) {
return child_titles.get(header_titles.get(groupPosition)).get(childPosition);
}
#Override
//return the groupo position
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
// Here return the Group View
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
// ListViewHolder viewHolder;
// if (view == null) {
// viewHolder = new ListViewHolder();
// LayoutInflater inflater = context.getLayoutInflater();
// view = inflater.inflate(R.layout.listitems, null, true);
// viewHolder.itmName = (TextView) view.findViewById(R.id.Item_name);
// viewHolder.itmPrice = (EditText) view.findViewById(R.id.Item_price);
// view.setTag(viewHolder);
// } else {
// viewHolder = (ListViewHolder) view.getTag();
//// loadSavedValues();
// }
// Here how to get the Heading Title here Decalered String Variables, now how to get title of heading from getGroup methods so simple call Backed Methods.
String title = (String) this.getGroup(groupPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.prent, null);
}
TextView textView = (TextView) convertView.findViewById(R.id.heading_item);
textView.setText(title); // for Heading bold style ,title
return convertView;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
String title = (String) this.getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.child, null);
}
String cellData = child_titles.get(header_titles.get(groupPosition)).get(childPosition);
EditText childItem = (EditText) convertView.findViewById(R.id.child_item);
childItem.setHint(cellData);
childItem.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// Log.d("xxxx", "Has focus " + hasFocus);
if (!hasFocus) {
// int itemIndex = View.getId();
// String enteredName = ((EditText)v).getText().toString();
// selttems.put(itemIndex, enteredName);
} else {
}
return;
}
});
return convertView;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public void setListData(HashMap<String, List<String>> lData) {
child_titles = lData;
}
public void setHeaderData(List<String> hData) {
header_titles = hData;
}
}
**child.Xml file**
<?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="50dp"
android:background="#ffff">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/child_item"
android:textSize="25dp"
android:textStyle="bold"
android:gravity="center_vertical"
android:layout_marginLeft="10dp"/>
<!--<EditText-->
<!--android:id="#+id/sequence"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_alignParentLeft="true"-->
<!--android:layout_alignParentTop="true"-->
<!--android:paddingLeft="35sp"-->
<!--android:layout_marginRight="10dp"-->
<!--android:textAppearance="?android:attr/textAppearanceMedium" />-->
</LinearLayout>
<!--This Layout File Represent the Child Items.
This Field Represent the Child Item IN the List VIew -->
**parent.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="50dp"
android:orientation="vertical">
<TextView
android:id="#+id/heading_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:gravity="center_vertical"
android:textColor="#color/colorAccent"
android:textSize="25dp" />
</LinearLayout>
<!--This Layout file for Heading -Lines.-->