How I go to the previous fragment when I click on back button.
RecyclerAdapter_1_ten.java
public class RecyclerAdapter_1_ten extends RecyclerView.Adapter<RecyclerAdapter_1_ten.ViewHolder> {
private String[] SubTxt = {"NCERT Solution",
"Notes"};
private int[] SubImage = {R.drawable.ic_answers_black_48dp,
R.drawable.ic_notes_black_48dp};
Activity activity;
public RecyclerAdapter_1_ten(Activity activity) {
this.activity = activity;
}
class ViewHolder extends RecyclerView.ViewHolder {
public int currentItem;
public ImageView itemImage;
public TextView itemTitle;
public ViewHolder(View itemView) {
super(itemView);
itemImage = (ImageView) itemView.findViewById(R.id.SubImage);
itemTitle = (TextView) itemView.findViewById(R.id.SubTxt);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
switch (position) {
case 0:
android.app.FragmentManager fm = activity.getFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, new SecondClass_10()).commit();
case 1:
Snackbar.make(v, "Comming Soon " + position,
Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
});
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recycler_1_9, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.itemTitle.setText(SubTxt[i]);
viewHolder.itemImage.setImageResource(SubImage[i]);
}
#Override
public int getItemCount() {
return SubTxt.length;
}
}
SecondClass_10.java
public class SecondClass_10 extends Fragment {
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
RecyclerView.Adapter adapter;
View rootview;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.second_class_10, container, false);
recyclerView = (RecyclerView) rootview.findViewById(R.id.recycler_ten_page_second);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter_2_ten();
recyclerView.setAdapter(adapter);
return rootview;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
android.app.FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, new FirstClass_9()).commit();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
android.app.FragmentManager fn = getFragmentManager();
int id = item.getItemId();
if (id == R.id.nav_9) {
fn.beginTransaction().replace(R.id.content_frame, new FirstClass_9()).commit();
} else if (id == R.id.nav_10) {
fn.beginTransaction().replace(R.id.content_frame, new FirstClass_10()).commit();
} else if (id == R.id.nav_11) {
fn.beginTransaction().replace(R.id.content_frame, new FirstClass_11()).commit();
} else if (id == R.id.nav_12) {
fn.beginTransaction().replace(R.id.content_frame, new FirstClass_12()).commit();
} else if (id == R.id.nav_aboutUs) {
} else if (id == R.id.nav_feedback) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
I follow many Tutorial but I didn't get solution Hope I'll get answer here. I have added recyclerview when I click on it it open fragment but when I click on back button instead of going back it goes to first Page.
How to go back to Fragment from Fragment when I click on Back button?
You can use Stack for holding the fragment instances. When you move to the next fragment push the fragment into the stack and detach it from your activity and in the onbackpressed event pop the fragment and attach it to the activity.
This is one of the best explanation that i came across when i started in SO for fragment navigation i hope it helps clear your understanding of how they work.
Android fragments navigation and backstack
Related
I am using recyclerview to retrieve data from firebase database which is working nicely but i have set default layout manager as linear but i want user must be able to switch from listview to gridview which is not working. It is not changing state when i click on on gridview item.It does nothing remains in the default state as linearlayout manager.
public class Welcome extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
FirebaseDatabase database;
DatabaseReference category;
TextView txtfullname;
RecyclerView recycler_menu;
RecyclerView.LayoutManager layoutManager;
FirebaseRecyclerAdapter<Category,MenuViewHolder> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Menu");
setSupportActionBar(toolbar);
//init firebase
database = FirebaseDatabase.getInstance();
category=database.getReference("Category");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
//set name for user
View headerView= navigationView.getHeaderView(0);
txtfullname= headerView.findViewById(R.id.nav_view);
// txtfullname.setText(Common.currentUser.getName());
//Load menu using firebase ui to bind data from frebase to recyclerview
recycler_menu =findViewById(R.id.recyclerview);
recycler_menu.setHasFixedSize(true);
layoutman();
recycler_menu.setLayoutManager(layoutManager);
loadMenu();
}
private void layoutman() {
layoutManager=new LinearLayoutManager(this);
}
private void loadMenu() {
adapter =new FirebaseRecyclerAdapter<Category, MenuViewHolder>(Category.class,R.layout.menu_item,MenuViewHolder.class,category) {
#Override
protected void populateViewHolder(MenuViewHolder viewHolder, Category model, int position) {
viewHolder.txtMenuName.setText(model.getName());
Picasso.with(getBaseContext()).load(model.getImage())
.into(viewHolder.imageView);
final Category clickItem = model;
viewHolder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Toast.makeText(Welcome.this,""+clickItem.getName(),Toast.LENGTH_SHORT).show();
}
});
}
};
recycler_menu.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.welcome, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if (id==R.id.list){
layoutman();
adapter.notifyDataSetChanged();
return true;
}
if (id==R.id.grid){
layoutManager=new GridLayoutManager(getApplicationContext(),2);
adapter.notifyDataSetChanged();
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_menu) {
// Handle the camera action
} else if (id == R.id.nav_cart) {
} else if (id == R.id.nav_orders) {
} else if (id == R.id.nav_log_out) {
} else if (id == R.id.share) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
You are doing right but have need to set layout manager on your recyclerview again otherwise it will not work and after that just call notifydatasetchanged() only after that it should work.
You have to change layout manager on click event , for example for Listview Data your layout manager should be
compile 'com.android.support:recyclerview-v7:23.2.0'
Below code for Grid View Layout Manager
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getApplicationContext(),2);
recyclerView.setLayoutManager(layoutManager);
For Simple Listview
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
then you have to change list view respectively, i hope this will help you
Good day How can I call a fragment when the users will click the card inside MyAdapter class. I want to replace view from the adapter. I am using recyclerview wants to perform click event using the view from my row layout.
Like for example when the user clicks the card it will open a fragment and it will show more data. Hope you can help me guys.
This is my main fragment
AccountsFragment
ReceivableFragment
LoanAppFragment
Those fragments hold different data. when the user clicks the cards inside that fragment it will call another fragment the SLDTLFragment.
Btw this MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Datas> 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 MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView account_type;
public TextView accnt_description;
public TextView balance_label;
public TextView account_balance;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
account_type = (TextView) v.findViewById(R.id.lblShareCapital);
balance_label = (TextView) v.findViewById(R.id.lblAvailableBalance);
accnt_description = (TextView) v.findViewById(R.id.sl_desc);
account_balance = (TextView) v.findViewById(R.id.actual_balance);
}
}
public MyAdapter(List<Datas> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
//holder.account_type.setText(mDataset[position]);
Datas datas = mDataset.get(position);
holder.accnt_description.setText(datas.getSL_DESC());
holder.account_balance.setText(datas.getACTUAL_BALANCE());
holder.mCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// String sl_desc = mDataset.get(position).getSL_DESC();
// String actual_balance = mDataset.get(position).getACTUAL_BALANCE();
String sle = mDataset.get(position).getSLE();
String slc = mDataset.get(position).getSLC();
String slt = mDataset.get(position).getSLT();
String ref_no = mDataset.get(position).getREF();
Log.d("CardView Clicked", "sle code: " + sle);
Log.d("CardView Clicked", "slc code: " + slc);
Log.d("CardView Clicked", "slt code: " + slt);
Log.d("CardView Clicked", "ref no: " + ref_no);
}
});
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
AccountsFragment.java
public class AccountsFragment extends Fragment {
private SQLiteHandler db;
public AccountsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_accounts, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
SQLiteHandler db = new SQLiteHandler(getActivity());
MyAdapter adapter = new MyAdapter(db.getUserSLDetails());
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
ReceivableFragment.java
public class ReceivableFragment extends Fragment {
public ReceivableFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_receivable, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
SQLiteHandler db = new SQLiteHandler(getActivity());
MyAdapter adapter = new MyAdapter(db.getUserSLARLoans());
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextView nav_header_name;
private TextView nav_header_email;
public TextView txtLogOut;
private SQLiteHandler db;
private SessionManager session;
private Timer timer;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Will replace the activity_main.xml to relativelayout_for_fragment.xml
if (savedInstanceState == null) {
AccountsFragment f1= new AccountsFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.relativelayout_for_fragment, f1);// relativelayout_for_fragment is inside the content_main.xml
fragmentTransaction.commit();
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View header=navigationView.getHeaderView(0);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
txtLogOut = (TextView) findViewById(R.id.nav_logout_menu);
int id = item.getItemId();
if (id == R.id.nav_deposit) {
// Handle the preference action
AccountsFragment accounts= new AccountsFragment();
FragmentManager manager= getSupportFragmentManager();
manager.beginTransaction()
.replace(R.id.relativelayout_for_fragment, accounts)
.commit();
Toast.makeText(MainActivity.this, "Deposit Accounts", Toast.LENGTH_SHORT).show();
}else if (id == R.id.nav_receivable) {
// Handle the Loan application();
ReceivableFragment receivable= new ReceivableFragment();
FragmentManager manager= getSupportFragmentManager();
manager.beginTransaction()
.replace(R.id.relativelayout_for_fragment, receivable)
.commit();
Toast.makeText(MainActivity.this, "AR and Loan Accounts", Toast.LENGTH_SHORT).show();
}else if (id == R.id.nav_apply_loan_menu) {
// Handle the Loan application();
LoanAppFragment loan_app= new LoanAppFragment();
FragmentManager manager= getSupportFragmentManager();
manager.beginTransaction()
.replace(R.id.relativelayout_for_fragment, loan_app)
.commit();
Toast.makeText(MainActivity.this, "This module is under developement", Toast.LENGTH_SHORT).show();
}else if (id == R.id.nav_logout_menu) {
// Handle the About action
logoutUser();
//Toast.makeText(MainActivity.this, "successfully Logout", Toast.LENGTH_LONG).show();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
});
nav_header_name = (TextView) header.findViewById(R.id.nav_name);
nav_header_email = (TextView) header.findViewById(R.id.nav_email);
// SqLite database handler
db = new SQLiteHandler(getApplicationContext());
// session manager
session = new SessionManager(getApplicationContext());
if (!session.isLoggedIn()) {
logoutUser();
}
//Fetching user details from SQLite
HashMap<String, String> user = db.getUserDetails();
String username = user.get("username");
String email = user.get("email");
//Displaying the user info in nav_header_main.xml
nav_header_name.setText(username);
nav_header_email.setText(email);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Logging out the user. Will set isLoggedIn flag to false in shared
* preferences Clears the user data from sqlite users table
* */
private void logoutUser() {
session.setLogin(false);
db.deleteUsers();
db.deleteUserSLDTL();
// Launching the login activity
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
#Override
protected void onPause() {
super.onPause();
timer = new Timer();
Log.i("Main", "Invoking logout timer");
LogOutTimerTask logoutTimeTask = new LogOutTimerTask();
timer.schedule(logoutTimeTask, 30000); // auto logout in 30secs inactivity
Log.i("Main", "Log out user due to inactivity");
}
#Override
protected void onResume() {
super.onResume();
if (timer != null) {
timer.cancel();
Log.i("Main", "cancel timer");
timer = null;
}
}
private class LogOutTimerTask extends TimerTask {
#Override
public void run() {
session.setLogin(false);
db.deleteUsers();
db.deleteUserSLDTL();
//redirect user to login screen
Intent i = new Intent(MainActivity.this, LoginActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
}
}
You need to use Listener/Callback pattern to inform your Activity or Fragment where the Adapter is used. Do not directly call a Fragment or activity inside of the Adapter because it will defeat the purpose of the Adapter. Adapter should only be used to show the data.
To implement the pattern, first create the interface and constructor to set the listener in your Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
...
private List<Datas> mDataset;
private ClickListener mListener;
public interface ClickListener {
void onItemClicked(YourData yourData);
}
public MyAdapter(List<Datas> myDataset, ClickListener listener) {
mDataset = myDataset;
mListener = listener;
}
...
}
Second, whenever there is a click of the item data, tell the listener with the following code in your Adapter:
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
...
holder.mCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// String sl_desc = mDataset.get(position).getSL_DESC();
// String actual_balance = mDataset.get(position).getACTUAL_BALANCE();
// String sle = mDataset.get(position).getSLE();
// String slc = mDataset.get(position).getSLC();
// String slt = mDataset.get(position).getSLT();
// String ref_no = mDataset.get(position).getREF();
// Simplify the above to a pojo. We assume the pojo is YourData
YourData data = new YourData();
// set the data from above.
mListener.onItemClicked(yourData);
});
}
Third, you need to set the listener in your Activity/Fragment which using the Adapter with:
MyAdapter.ClickListener listener = new MyAdapter.ClickListener() {
#Override
public void onItemClicked(YourData yourData) {
// Do something with the data here.
}
};
MyAdapter adapter = new MyAdapter(db.getUserSLARLoans(), listener);
rv.setAdapter(adapter);
You need to handle the data in your listener inside the onItemClicked() method above.
try to pass getFragmentManager using constructor and then replace the view with container view in your item row.
//constructor
public MyAdapter(FragmentManager fragment, List<Datas> myDataset) {
mDataset = myDataset;
mFragment = fragment;
}
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public CardView mCardView;
public TextView account_type;
public TextView accnt_description;
public TextView balance_label;
public TextView account_balance;
public MyViewHolder(View v){
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
account_type = (TextView) v.findViewById(R.id.lblShareCapital);
balance_label = (TextView) v.findViewById(R.id.lblAvailableBalance);
accnt_description = (TextView) v.findViewById(R.id.sl_desc);
account_balance = (TextView) v.findViewById(R.id.actual_balance);
mCardView.setOnClickListener(this)
}
#Override
public void onClick(View view){
mFragment.beginTransaction().replace(R.id.containerRow,new MyFragment()).commit();
}
}
//note this is not tested code.
I'm new to Android and I started building a "Navigation Drawer Activity" project. I added a TabLayout and ViewPager to my activity_main.xml and now I can swipe between different lists. When I click an item in a list, it calls onListFragmentInteraction in my MainActivity.java. I tried the code below to dynamically add a Detail fragment when a user clicks an item in the list, but I get this error. My MainActivity class does "implement CustomerFragment.OnListFragmentInteractionListener"
First, is my attempt at showing a detail fragment inside a ViewPager correct? Would the code I am attempting below add a fragment in the current tab?
Secondly, does anyone know why I am getting this error?
Thanks so much!
Error:
java.lang.RuntimeException: com.myproject.android.MainActivity#186e12d
must implement OnFragmentInteractionListener
MainActivity:
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, TabLayout.OnTabSelectedListener, CustomerFragment.OnListFragmentInteractionListener, GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private TabLayout tabLayout;
private ViewPager viewPager;
private Pager adapter;
public void onListFragmentInteraction(Customer customer){
FragmentManager fm = getSupportFragmentManager();
CustomerDetailFragment fragment = CustomerDetailFragment.newInstance(customer);
fm.beginTransaction().add(R.id.pager, fragment).commit();
}
#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) { }
#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) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Home"));
tabLayout.addTab(tabLayout.newTab().setText("Customers"));
tabLayout.addTab(tabLayout.newTab().setText("Jobs"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager = (ViewPager) findViewById(R.id.pager);
adapter = new Pager(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
FirebaseMessaging.getInstance().subscribeToTopic("global");
String token = FirebaseInstanceId.getInstance().getToken();
// Check Google Play Services
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.build();
// test
Date d = new Date();
DbHandler dbHandler = new DbHandler(this, null, null, 1);
Customer customer = new Customer(1, 1, 1, 1, "Test", "Test", "Test", false, d, 1, d, 1);
dbHandler.addCustomer(customer);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
startActivity(new Intent(this, LoginActivity.class));
} else if (id == R.id.nav_gallery) {
startActivity(new Intent(this, SyncActivity.class));
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
Customer List Fragment:
public class CustomerFragment extends Fragment {
private OnListFragmentInteractionListener mListener;
public CustomerFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_customer_list, container, false);
SearchView sv = (SearchView) view.findViewById(R.id.searchview);
RecyclerView rv = (RecyclerView) view.findViewById(R.id.recyclerview);
// Adapter
rv.setLayoutManager(new LinearLayoutManager(view.getContext()));
final CustomerAdapter adapter = new CustomerAdapter(getCustomers(), mListener);
rv.setAdapter(adapter);
// Search
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String query) {
//adapter.getFilter().filter(query);
return false;
}
});
return view;
}
private ArrayList<Customer> getCustomers() {
DbHandler dbHandler = new DbHandler(this.getActivity(), null, null, 1);
ArrayList<Customer> customers = dbHandler.getCustomers();
return customers;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement OnListFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnListFragmentInteractionListener {
void onListFragmentInteraction(Customer customer);
}
}
Customer Adapter:
public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.ViewHolder> {
private final List<Customer> mValues;
private final OnListFragmentInteractionListener mListener;
public CustomerAdapter(List<Customer> items, OnListFragmentInteractionListener listener) {
mValues = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_customer, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Customer customer = mValues.get(position);
holder.mItem = customer;
holder.mIdView.setText(String.valueOf(customer.getId()));
holder.mContentView.setText(customer.getCompanyName());
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (null != mListener) {
mListener.onListFragmentInteraction(holder.mItem);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public Customer mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
UPDATE: It looks like I needed to add both onListFragmentInteraction AND onFragmentInteraction. The first is for the CustomerListFragment and the 2nd is for the CustomerDetailFragment.
And to get the CustomerDetailFragment working with the tabs, I followed this and got it working:
https://medium.com/#nilan/separate-back-navigation-for-a-tabbed-view-pager-in-android-459859f607e4#.lrjeexdcp
#Override
public void onListFragmentInteraction(Customer customer){
FragmentManager fm = getSupportFragmentManager();
CustomerDetailFragment fragment = CustomerDetailFragment.newInstance(customer);
fm.beginTransaction().add(R.id.pager, fragment).commit();
}
#Override
public void onFragmentInteraction(Uri uri) {
}
You need to put
public void onListFragmentInteraction(Customer customer){
FragmentManager fm = getSupportFragmentManager();
CustomerDetailFragment fragment = CustomerDetailFragment.newInstance(customer);
fm.beginTransaction().add(R.id.pager, fragment).commit();
}
Inside your MainActivity class instead of outside of it.
If that's not actually how your code is, edit your answer to break up the blocks to accurately represent how your code is built and include your interfance inside the fragment for the listener. You also may need the #Override tag above the onListFragmentInteraction implementation
Edit
As I mentioned above you need to put the #Override tag above the onListFragmentInteraction implementation, look at every other listener implementation you already have.
I want to play a mp3 with ImageButton in Fragment.
here is my code:
public class FirstFragment extends Fragment {
View myView;
MediaPlayer mp;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.first_layout, container, false);
return myView;
ImageButton btn = (ImageButton)getView().findViewById(R.id.paratha);
//on click button for paratha
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer paratha = MediaPlayer.create(this, R.raw.paratha);
paratha.start();
}
});
}
}
You set your click listener below return statement. This is wrong, also the context should be getActivity() instead this in MediaPlayer, because you use fragment not an activity. Change your method like that:
View myView;
MediaPlayer mp;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.first_layout, container, false);
ImageButton btn = (ImageButton)myView.findViewById(R.id.paratha);
//on click button for paratha
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer paratha = MediaPlayer.create(getActivity(), R.raw.paratha);
paratha.start();
}
});
return myView;
}
Hope it help!
Your nextscreen() method should looks like that:
public void nextscreen() {
SecondFragment fragment = new SecondFragment();
FragmentManager fragmentManager = getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
You want to make intent but you need transaction to load you second fragment.
i want to move next screen, after mediaplayer finished the audio.
public class FirstFragment extends Fragment {
View myView;
MediaPlayer mp;
ImageButton btn;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.first_layout, container, false);
btn = (ImageButton) myView.findViewById(R.id.paratha);
//on click button for paratha
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer paratha = MediaPlayer.create(getActivity(), R.raw.paratha);
paratha.start();
paratha.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
nextscreen();
}
});
}
});
return myView;
}
public void nextscreen() {
Intent intent = new Intent(getActivity(), SecondFragment.class);
getActivity().startActivity(intent);
}
}
MainActivity file is here:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
FragmentManager fragmentManager = getFragmentManager();
if (id == R.id.nav_first_layout) {
fragmentManager.beginTransaction()
.replace(R.id.content_frame
, new FirstFragment())
.commit();
// Handle the camera action
} else if (id == R.id.nav_second_layout) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
second_layout xml file:
public class SecondFragment extends Fragment {
View secView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
secView = inflater.inflate(R.layout.second_layout, container, false);
return secView;
}
}
I am using navigation drawer which calls multiple fragments on the click of a list item of navigation drawer.
In my scenario, parent activity handles 2 fragments. There is an expected behavior that I am facing in handling these fragments.
Here is what I am doing:
Go to offline mode -> Go to fragment 2 -> Minimize the app -> Go to online mode ( switch on the internet ) - > Resume the app
On resume of the app, the parent activity is called and in parent activity, by default fragment 1 is opened, rather it should open fragment 2.
Help is appreciated.
Here is my navigation drawer code -
public class NavigationDrawer extends ActionBarActivity implements OnItemClickListener {
private ActionBar actionBar;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
RelativeLayout user_panel;
LinearLayout mylinearlayout;
private ActionBarDrawerToggle mDrawerToggle;
// Initialize SharedPreferences and editor variable's.
SharedPreferences.Editor editor;
SharedPreferences pref;
String username;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_drawer);
// Initialize SharedPreferences mode
pref = getApplicationContext().getSharedPreferences("MyPref", 0);
editor = pref.edit();
username = pref.getString("name", null); // getting String
moveDrawerToTop();
initActionBar();
initDrawer();
//Quick cheat: Add Fragment 1 to default view
onItemClick(null, null, 0, 0);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
private void moveDrawerToTop() {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DrawerLayout drawer = (DrawerLayout) inflater.inflate(R.layout.decor, null); // "null" is important.
// HACK: "steal" the first child of decor view
ViewGroup decor = (ViewGroup) getWindow().getDecorView();
View child = decor.getChildAt(0);
decor.removeView(child);
LinearLayout container = (LinearLayout) drawer.findViewById(R.id.drawer_content); // This is the container we defined just now.
container.addView(child, 0);
drawer.findViewById(R.id.drawer).setPadding(0, getStatusBarHeight(), 0, 0);
ImageView profile = (ImageView) drawer.findViewById(R.id.image_view);
profile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
// Make the drawer replace the first child
decor.addView(drawer);
}
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
private int getContentIdResource() {
return getResources().getIdentifier("content", "id", "android");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
mDrawerToggle.syncState();
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
int id = item.getItemId();
if (id == R.id.notification) {
Intent display_notify = new Intent(getApplicationContext(), DisplayActivity.class);
startActivity(display_notify);
return true;
}
return super.onOptionsItemSelected(item);
}
private void initActionBar() {
actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
}
private void initDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mylinearlayout = (LinearLayout) findViewById(R.id.drawer);
mDrawerLayout.setDrawerListener(createDrawerToggle());
mDrawerList = (ListView) findViewById(R.id.MyList);
user_panel = (RelativeLayout) findViewById(R.id.user_profile_panel);
user_panel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
TextView user_name = (TextView) findViewById(R.id.left_panel_user_name);
user_name.setText(username);
ListAdapter adapter = (ListAdapter) (new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.nav_items)));
mDrawerList.setAdapter(adapter);
mDrawerList.setOnItemClickListener(this);
}
private DrawerListener createDrawerToggle() {
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
#Override
public void onDrawerStateChanged(int state) {
}
};
return mDrawerToggle;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mDrawerLayout.closeDrawer(mylinearlayout);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ftx = fragmentManager.beginTransaction();
if (position == 0) {
ftx.replace(R.id.main_content, new FragmentOne());
} else if (position == 1) {
ftx.replace(R.id.main_content, new FragmentSecond());
} else if (position == 2) {
} else if (position == 3) {
} else if (position == 4) {
invitation();
} else if (position == 5) {
launchMarket();
} else if (position == 6) {
ftx.replace(R.id.main_content, new Setting_Fragment());
}
ftx.commit();
}
}