Launching BottomSheet from a RecyclerViewAdapter that extends with RecyclerView.Adapter inside onBindViewHolder - java

I have a Card View in a layout that has a two Text Views and an Image View and i have a Recycler View that uses the Card View to set items. What i want to achieve is to launch a Bottom Sheet when the Card View is tapped
Here is the code in Main Activity
Code for List
List<Item> lstItem;
lstItem = new ArrayList<>();
lstItem.add(new Item("Samsung","Smartphones","QualitlstItem = new ArrayList<>();y Samsung Smartphones",R.drawable.samsung,"21000"));
lstItem.add(new Item("Lenovo","Smartphones","Quality Lenovo smartphones",R.drawable.lenovo,"15000"));
Code for attaching Recycler View Adapter to Main Activity
FragmentManager fragmentManager = getSupportFragmentManager();
RecyclerViewAdapter2 mainAdapter2 = new RecyclerViewAdapter2(lstItem,fragmentManager);
mainRecyclerView.setLayoutManager(new GridLayoutManager(this,3));
mainRecyclerView.setAdapter(mainAdapter2);
Recycler View Adapter 2 Code
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class RecyclerViewAdapter2 extends RecyclerView.Adapter<RecyclerViewAdapter2.MyViewHolder> {
private Context context;
private List<Item> data;
private FragmentManager fragmentManager;
public RecyclerViewAdapter2(List<Item> data, FragmentManager fragmentManager) {
this.data = data;
this.fragmentManager = fragmentManager;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_items, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv_item_title.setText(data.get(position).getTitle());
holder.price.setText(data.get(position).getPrice());
holder.item_thumbnail.setImageResource(data.get(position).getThumbnail());
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
}
});
}
#Override
public int getItemCount() {
return data.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_item_title;
TextView price;
ImageView item_thumbnail;
CardView cardView;
public MyViewHolder(View itemView){
super(itemView);
tv_item_title = itemView.findViewById(R.id.itemTitleId);
price = itemView.findViewById(R.id.priceId);
item_thumbnail = itemView.findViewById(R.id.itemThumbnailId);
cardView = itemView.findViewById(R.id.cardView);
}
}
}
This is where am having a problem: Launching Bottom Sheet on Card View Click:
BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(getSupportFragmentManager(), bottomSheetFragment.getTag());
BottomSheetFragment Code;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
public class BottomSheetFragment extends BottomSheetDialogFragment {
public BottomSheetFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.bottomsheet1, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//String s=getArguments().getString("myString");
}
}
I have tried the following inside onBindViewHolder:
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv_item_title.setText(data.get(position).getTitle());
holder.price.setText(data.get(position).getPrice());
holder.item_thumbnail.setImageResource(data.get(position).getThumbnail());
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity appCompatActivity = new AppCompatActivity();
FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(fragmentManager, bottomSheetFragment.getTag());
}
});
}
Here is the Error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: manu.apps.victortestapp, PID: 16271
java.lang.IllegalStateException: Activity has been destroyed
at androidx.fragment.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2114)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:683)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:637)
at androidx.fragment.app.DialogFragment.show(DialogFragment.java:144)
at manu.apps.victortestapp.RecyclerViewAdapter2$1.onClick(RecyclerViewAdapter2.java:52)
at android.view.View.performClick(View.java:6726)
at android.view.View$PerformClick.run(View.java:25434)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6524)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:451)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:888)
I want to open BottomSheet when the Card View inside the Recycler View is tapped

In your onClick Listener, you need to use the fragmentManager you are passing to the Adapter. Instead you use getSupportFragmentManager(). After changing this it works for me.
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
// <-- Here change getSupportFragmentManager() to fragmentManager
bottomSheetFragment.show(fragmentManager, bottomSheetFragment.getTag());
}
});

to call BottomSheetDialog Fragment from RecyclerView.Adapter. Try this it worked fine for me.
DialogFragment bottomSheetDialogFragment = new BottomsheetDialog();
bottomSheetDialogFragment.show(((FragmentActivity)mContext).getSupportFragmentManager(), bottomSheetDialogFragment.getTag());

You can't do this:
AppCompatActivity appCompatActivity = new AppCompatActivity();
FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
BottomSheetFragment bottomSheetFragment = new BottomSheetFragment();
bottomSheetFragment.show(fragmentManager, bottomSheetFragment.getTag());
You should create a new Activity ( a new class ) that will contain your BottomSheetFragment and start that activity using an intent.

Related

How do I set onClick listener to recyclerView?

I want to add onClick to recyclerView to send data back to form Activity for update data process. How can I implement onItemClickListner when this code doesn't have adapter in it?
Show_Employees.java:
package com.example.roomdatabaseandroid;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.roomdatabaseandroid.DataModel.EmployeeDao;
import com.example.roomdatabaseandroid.DataModel.EmployeeDatabase;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class ShowEmployees extends AppCompatActivity {
private static final int EDIT_COURSE_REQUEST = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_employees);
RecyclerView recyclerView;
FloatingActionButton fab = findViewById(R.id.idFABAdd);
EmployeeDao employeeDao;
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//starting a new activity for adding a new course and passing a constant value in it.
Intent intent = new Intent(ShowEmployees.this, MainActivity.class);
startActivity(intent);
}
});
employeeDao = EmployeeDatabase.getDBInstance(this).employeeDao();
recyclerView = findViewById(R.id.employeeRecyclerView);
EmployeeRecycler employeeRecycler = new EmployeeRecycler(employeeDao.getAllEmployee());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(employeeRecycler);
//below method is use to add swipe to delete method for item of recycler view.
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
//on recycler view item swiped then we are deleting the item of our recycler view.
employeeDao.deleteEmployee(employeeRecycler.data.get(viewHolder.getAdapterPosition()));
Toast.makeText(ShowEmployees.this, "Employee deleted", Toast.LENGTH_SHORT).show();
}
}).attachToRecyclerView(recyclerView);
}
}
Employee_Recycler.java:
package com.example.roomdatabaseandroid;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.roomdatabaseandroid.DataModel.DataConverter;
import com.example.roomdatabaseandroid.DataModel.Employee;
import java.util.List;
public class EmployeeRecycler extends RecyclerView.Adapter<EmployeeViewHolder> {
List<Employee> data;
public EmployeeRecycler(List<Employee> employees){
data = employees;
}
#NonNull
#Override
public EmployeeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_1,
parent,false
);
return new EmployeeViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull EmployeeViewHolder holder, int position) {
Employee employee = data.get(position);
holder.imageView.setImageBitmap(DataConverter.convertByteArraytoImage(employee.getImage()));
holder.firstName.setText(employee.getFirstName());
holder.middleName.setText(employee.getMiddleName());
holder.lastName.setText(employee.getLastName());
holder.dob.setText(employee.getDOB());
holder.gender.setText(employee.getGender());
holder.address.setText(employee.getAddress());
holder.designation.setText(employee.getDesignation());
holder.email.setText(employee.getEmail());
holder.phoneNumber.setText(employee.getPhoneNumber());
}
#Override
public int getItemCount() {
return data.size();
}
}
EmployeeViewHolder.java:
package com.example.roomdatabaseandroid;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class EmployeeViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView firstName,middleName,lastName,email,phoneNumber,address,designation,gender,dob;
public EmployeeViewHolder(#NonNull View itemView) {
super(itemView);
firstName = itemView.findViewById(R.id.idTVFirstName);
middleName = itemView.findViewById(R.id.idTVMiddleName);
lastName = itemView.findViewById(R.id.idTVLastName);
dob = itemView.findViewById(R.id.idTVDOB);
address = itemView.findViewById(R.id.idTVAddress);
gender = itemView.findViewById(R.id.idTVGender);
designation = itemView.findViewById(R.id.idTVDesignation);
email = itemView.findViewById(R.id.idTVEmail);
phoneNumber = itemView.findViewById(R.id.idTVPhoneNumber);
imageView = itemView.findViewById(R.id.profileImageView);
}
}
add an interface
interface AdapterItemClickListener {
void onItemClickListener(Employee employee, int position)
}
your actvity must implement this interface
public class ShowEmployees extends AppCompatActivity implements AdapterItemClickListener {
private static final int EDIT_COURSE_REQUEST = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_employees);
RecyclerView recyclerView;
FloatingActionButton fab = findViewById(R.id.idFABAdd);
EmployeeDao employeeDao;
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//starting a new activity for adding a new course and passing a constant value in it.
Intent intent = new Intent(ShowEmployees.this, MainActivity.class);
startActivity(intent);
}
});
employeeDao = EmployeeDatabase.getDBInstance(this).employeeDao();
recyclerView = findViewById(R.id.employeeRecyclerView);
EmployeeRecycler employeeRecycler = new EmployeeRecycler(employeeDao.getAllEmployee(), this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(employeeRecycler);
//below method is use to add swipe to delete method for item of recycler view.
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
//on recycler view item swiped then we are deleting the item of our recycler view.
employeeDao.deleteEmployee(employeeRecycler.data.get(viewHolder.getAdapterPosition()));
Toast.makeText(ShowEmployees.this, "Employee deleted", Toast.LENGTH_SHORT).show();
}
}).attachToRecyclerView(recyclerView);
}
void onItemClickListener(Employee employee, int position) {
//update or another job
}
}
and your adapter
public class EmployeeRecycler extends RecyclerView.Adapter<EmployeeViewHolder> {
List<Employee> data;
AdapterItemClickListener itemClickListener;
public EmployeeRecycler(List<Employee> employees, AdapterItemClickListener itemClickListener){
data = employees;
this.itemClickListener = itemClickListener;
}
#NonNull
#Override
public EmployeeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_1,
parent,false
);
return new EmployeeViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull EmployeeViewHolder holder, int position) {
Employee employee = data.get(position);
holder.imageView.setImageBitmap(DataConverter.convertByteArraytoImage(employee.getImage()));
holder.firstName.setText(employee.getFirstName());
holder.middleName.setText(employee.getMiddleName());
holder.lastName.setText(employee.getLastName());
holder.dob.setText(employee.getDOB());
holder.gender.setText(employee.getGender());
holder.address.setText(employee.getAddress());
holder.designation.setText(employee.getDesignation());
holder.email.setText(employee.getEmail());
holder.phoneNumber.setText(employee.getPhoneNumber());
holder.itemView.setOnClickListener (v -> {
itemClickListener.onItemClickListener(employee, position);
});
}
#Override
public int getItemCount() {
return data.size();
}
}

Android RecyclerView Showing only one item from 100

i'm new to android programming, i have a issue with a recyclerview ( i'm reading an android programming book and practice ) : it's showing only one item although i passed a list of 100 items
here's the code of the class:
package com.training.criminalintent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class CrimeListFragment extends Fragment {
private RecyclerView mCrimeRecyclerView;
private CrimeAdapter mAdapter;
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_crime_list, container, false);
mCrimeRecyclerView = (RecyclerView) view
.findViewById(R.id.crime_recycler_view);
mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private Crime mCrime;
private TextView mTitleTextView;
private TextView mDateTextView;
private CheckBox mSolvedCheckBox;
public CrimeHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mTitleTextView = (TextView)
itemView.findViewById(R.id.list_item_crime_title_text_view);
mDateTextView = (TextView)
itemView.findViewById(R.id.list_item_crime_date_text_view);
mSolvedCheckBox = (CheckBox)
itemView.findViewById(R.id.list_item_crime_solved_check_box);
}
public void bindCrime(Crime crime) {
mCrime = crime;
mTitleTextView.setText(mCrime.getTitle());
mDateTextView.setText(mCrime.getDate().toString());
mSolvedCheckBox.setChecked(mCrime.isSolved());
}
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), CrimeActivity.class);
startActivity(intent);
}
}
private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {
private List<Crime> mCrimes;
public CrimeAdapter(List<Crime> crimes) {
mCrimes = crimes;
}
#Override
public int getItemCount() {
return mCrimes.size();
}
#Override
public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater
.inflate(R.layout.list_item_crime, parent, false);
return new CrimeHolder(view);
}
#Override
public void onBindViewHolder(CrimeHolder holder, int position) {
Crime crime = mCrimes.get(position);
holder.bindCrime(crime);
}
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
mAdapter = new CrimeAdapter(crimes);
mCrimeRecyclerView.setAdapter(mAdapter);
}
}
Thanks in advance for you help,
The book somehow made a mistake.
The actual input should be android:layout_height="wrap_content"
Thanks yo your answer. Indeed my mistake was the recyclerView attribute android:layout_height.
I put match_parent instead of wrap_content

view pager is swiping same image again and again

i have been working on app (Question Answer based) . I have included view pager to swipe the image but it's only swiping same image .
code of class which call a class (where view pager is included in activity)
package com.example.joshiyogesh.puzzle;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class ExerciseOneQuestionList extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise_one_question_list);
}
public void questionOne(View view) {
Intent intent = new Intent(getApplicationContext(),ExerciseOneQuestions.class);
intent.putExtra("question_index",0);
startActivity(intent);
}
}
ExerciseOneQuestion.java
package com.example.joshiyogesh.puzzle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class ExerciseOneQuestions extends AppCompatActivity {
ViewPager viewPager;
public int questionIndexReceive;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise_one_questions);
questionIndexReceive = getIntent().getIntExtra("question_index",1);
// questionIndexReceive =Integer.parseInt(getIntent().getStringExtra("question_index"));
viewPager = (ViewPager)findViewById(R.id.pager);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
}
}
pager Adapter class
package com.example.joshiyogesh.puzzle;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class PagerAdapter extends FragmentPagerAdapter {
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
position = new ExerciseOneQuestions().questionIndexReceive;
Fragments fragments = new Fragments();
Bundle bundle = new Bundle();
bundle.putInt("question_no",position);
fragments.setArguments(bundle);
return fragments;
}
#Override
public int getCount() {
return 2;
}
}
fragments class
public class Fragments extends Fragment {
ImageView imageView;
#Override
public View onCreateView(LayoutInflater inflater , ViewGroup container ,
Bundle savedInstanceState){
int [] image_index = {R.drawable.eightypageanswer1,R.drawable.eightypageanswer8};
Bundle bundle = getArguments();
int message = bundle.getInt("question_no");
View rootView = inflater.inflate(R.layout.fragments,container,false);
imageView = (ImageView) rootView.findViewById(R.id.imageQuestions);
imageView.setImageResource(image_index[message]);
return rootView;
}
}
for testing purpose I have considered only two images in integer, But its always swiping same image i.e first image.
instead of changing "question_index" in ExerciseOneQuestionList.java
here ...
public void questionOne(View view) {
Intent intent = new Intent(getApplicationContext(),ExerciseOneQuestions.class);
intent.putExtra("question_index",0);
startActivity(intent);
}
couldn't understand why its always showing same image ?
It seems that problem is in line
position = new ExerciseOneQuestions().questionIndexReceive;
It seems that position is always set on the same number.
I really dont know what you are doing with this " new ExerciseOneQuestions().questionIndexReceive;" line. But in standard way you should have make two fragments then add these fragments to your adapter. Rest of thing will be done by adapter , following rough code may help you :
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position); // Which Fragment should be dislpayed by the viewpager for the given position
}
#Override
public int getCount() {
return mFragments.size();
}
}
Make two fragments object in class add them in adapter by calling addFragment method and then setadapter.

IllegalStateException while acessing FragmentManager inside RecyclerAdapter class with the help of activity's object

I am trying to open a dialog box from my Recycler adapter onClick of a button.
For that i need to get the FragmentManager using the getFragmentManager method ,which can only be called with the help of the activity object .
Here is my code :
RecyclerAdapter2 :
package com.example.batrad.expenseassist;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.media.Image;
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.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Collections;
import java.util.List;
/**
* Created by batrad on 11/18/2016.
*/
public class RecyclerAdapter2 extends RecyclerView.Adapter<RecyclerAdapter2.MyViewHolder> {
List<Information2> data = Collections.emptyList();
private LayoutInflater inflator;
Activity activity;
FragmentManager fm;
public RecyclerAdapter2(Context context, List<Information2> data) {
activity=(Activity)context;
inflator = LayoutInflater.from(context);
this.data = data;
fm=activity.getFragmentManager();
}
#Override
public RecyclerAdapter2.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =inflator.inflate(R.layout.recycler_row_category,parent,false);
MyViewHolder holder=new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(RecyclerAdapter2.MyViewHolder holder, int position) {
Log.d("tag",data.get(0)+"");
Information2 info=data.get(position);
Log.d("testre",info.categoryName+info.amount);
holder.categoryName.setText(info.categoryName);
holder.amount.setText(info.amount+"");
holder.categoryImage.setImageResource(info.categoryImage);
}
public void onInsert(int size){
notifyItemInserted(size);
}
#Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView categoryName;
TextView amount;
ImageView categoryImage;
ImageView deleteIcon;
ImageView addIcon;
public MyViewHolder(View itemView) {
super(itemView);
categoryName=(TextView) itemView.findViewById(R.id.categoryName);
amount=(TextView) itemView.findViewById(R.id.amount);
categoryImage=(ImageView) itemView.findViewById(R.id.categoryImage);
deleteIcon=(ImageView) itemView.findViewById(R.id.deleteIcon);
addIcon=(ImageView) itemView.findViewById(R.id.addIcon);
addIcon.setOnClickListener(this);
}
#Override
public void onClick(View view) {
SubCategoryDialog subCategoryDialog=new SubCategoryDialog();
SubCategoryDialog.setValues(data.get(getAdapterPosition()).categoryName);
subCategoryDialog.show(fm, "Create Category");
}
}
}
Inside the constructor of RecyclerAdapter2 I am passing the context of the activity from my MainActivity Java file:
MainActivity.java :
categoryrecycleAdapter = new RecyclerAdapter2(this, getdata());
Inside RecyclerAdapter2 constructor i assign the context to Activity class's object .
And than i use the object to get the fragmentManager.
But i am getting IllegalStateException here :
java.lang.IllegalStateException: Activity has been destroyed
at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1433)
at android.app.BackStackRecord.commitInternal(BackStackRecord.java:687)
at android.app.BackStackRecord.commit(BackStackRecord.java:663)
at android.app.DialogFragment.show(DialogFragment.java:230)
at com.example.batrad.expenseassist.RecyclerAdapter2$MyViewHolder.onClick(RecyclerAdapter2.java:85)
at android.view.View.performClick(View.java:5233)
at android.view.View$PerformClick.run(View.java:21209)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:152)
Please help .
This is not the right way to attach listeners. You should set the onClickListener in the constructor of your viewholder and should send a callback to your fragment using an interface as shown below or you can also use BaseAdapter from this or this.
public interface OnItemClickListener {
void onItemClick(View v);
}
private final OnItemClickListener listener;
public RecAdapter(OnItemClickListener listener) {
this.listener = listener;
}
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemCLick(v);
}
});
}

Android fragment tabbed layout, reselecting tab 3, listview disappears

When I select tab 3 my listview appears, yet when I select tab 1 and reselect tab 3, the listview doesn't appear.
Why is this?
https://github.com/jdavey1996/News-Android-App
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Local"));
tabLayout.addTab(tabLayout.newTab().setText("Top rated"));
tabLayout.addTab(tabLayout.newTab().setText("All"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
}
package com.josh_davey.news_app;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class FragmentAdapter extends FragmentPagerAdapter {
int count;
public FragmentAdapter(FragmentManager fm, int count) {
super(fm);
this.count = count;
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
Fragment1 temp = new Fragment1();
return temp;
case 1:
Fragment2 temp2 = new Fragment2();
return temp2;
case 2:
Fragment3 temp3 = new Fragment3();
return temp3;
}
return null;
}
#Override
public int getCount() {
return count;
}
}
package com.josh_davey.news_app;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment3 extends Fragment {
public Fragment3() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GetData getData = new GetData(getContext(),getActivity());
getData.execute("lincoln");
}
#Override
public void onResume() {
super.onResume();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment3, container, false);
}
}
If you need link to the full code it's on my github. Thanks in advance for any help
https://github.com/jdavey1996/News-Android-App
Default ViewPager's offscreenPageLimit is 1. So the tab3 is detached when tab1 is re-selected. If fragment is detached, Fragment's views are destroyed.
see: ViewPager.setOffscreenPageLimit
So I recommend you to set offscreenPageLimit to 2.
viewPager.setOffscreenPageLimit(2);
Or you can hold the list of ArticleConstructor in Fragment3 like blew.
GetData.java:
public class GetData extends AsyncTask<String, String,ArrayList<ArticleConstructor>>{
Callback callback;
interface Callback {
void onArticleConstructorLoaded(ArrayList<ArticleConstructor> articleConstructors);
}
public GetData(Callback callback) {
this.callback = callback;
}
...
#Override
protected void onPostExecute(ArrayList<ArticleConstructor> result) {
callback.onArticleConstructorLoaded(result);
}
....
}
Fragment3.java:
public class Fragment3 extends Fragment implements GetData.Callback {
private ListView listView;
private ArrayList<ArticleConstructor> articleConstructors = new ArrayList<>();
private ArticleArrayAdapter adapter;
public Fragment3() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment3, container, false);
listView = (ListView) view.findViewById(R.id.listView);
adapter = new ArticleArrayAdapter(getActivity(), getContext(), articleConstructors);
listView.setAdapter(adapter);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (articleConstructors.size() == 0) {
GetData getData = new GetData(this);
getData.execute("lincoln");
}
}
#Override
public void onArticleConstructorLoaded(ArrayList<ArticleConstructor> articleConstructors) {
this.articleConstructors = articleConstructors;
adapter.setArticleConstructors(articleConstructors);
}
}

Categories

Resources