I've successfully implemented cardview and recycleview in my navigation drawer. Now the problem is, when ever I clicked in my first cardview which will take me to my first fragment and then press back, my cardviews aren't in my list tab(1st fragment) anymore. The only option view the list of cardviews is to swipe to my navigation drawer again and click on the first fragment to view the cardviews.
here's my code for the
RecyclerViewAdapter.class
package com.example.guitarista.citem.Exhibitor;
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.guitarista.citem.Gallery_SpringForward.GalleryFragment;
import com.example.guitarista.citem.Gallery_activity.GalleryActivity;
import com.example.guitarista.citem.R;
import java.util.List;
/**
* Created by smdojt on 1/24/2017.
*/
public class TabInt_RV_Adapter extends RecyclerView.Adapter<TabInt_RV_Adapter.ItemViewHolder> {
public static class ItemViewHolder extends RecyclerView.ViewHolder {
static CardView cv;
TextView itemName;
TextView itemCathegory;
ImageView itemPhoto;
ItemViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
itemName = (TextView) itemView.findViewById(R.id.item_name);
itemCathegory = (TextView) itemView.findViewById(R.id.item_cathegory);
itemPhoto = (ImageView) itemView.findViewById(R.id.item_photo);
}
}
List<Exhibitors_Int> items;
Context context;
TabInt_RV_Adapter(List<Exhibitors_Int> items, Context context) {
this.context = context;
this.items = items;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_exhibitor_tabint_item, viewGroup, false);
ItemViewHolder ivh = new ItemViewHolder(v);
return ivh;
}
#Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, final int i) {
itemViewHolder.cv.setOnClickListener(null);
itemViewHolder.itemName.setText(items.get(i).name);
itemViewHolder.itemCathegory.setText(items.get(i).cathegory);
itemViewHolder.itemPhoto.setImageResource(items.get(i).photoId);
ItemViewHolder.cv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (i == 1) {
//Toast.makeText(context, "Index position is 1", Toast.LENGTH_SHORT).show();
Intent intent = new Intent (context, GalleryActivity.class);
context.startActivity(intent);
}
else if (i == 2) {
//Toast.makeText(context, "Index position is 2 ", Toast.LENGTH_SHORT).show();
AppCompatActivity activity = (AppCompatActivity) v.getContext();
GalleryFragment gf = new GalleryFragment();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, gf).addToBackStack(null).commit();
}
}
});
}
#Override
public int getItemCount() {
return items.size();
}
}
notice that on my onClick, there's two versions of gallery. The first one is the original activity, and the second one is implemented for fragment.
So when I clicked on the first one, and then back pressed, the cardviews will show. Now whats the problem with this? I cant swipe through navigation drawer when I click the activity version of gallery.
Where in, when I clicked on the second cardview which is fragment implemented, the navigation drawer swipe does work while inside the gallery, but when I press back, the lists of cardviews wont show.
even when I put these lines of code for fragment:
GalleryFragment fr = new GalleryFragment();
Bundle args = new Bundle();
fr.setArguments(args);
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fr);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
I'll just even get an error for getFragmentManager();
Is there any other way to solve this?
CODE FOR CARDVIEWS
package com.example.guitarista.citem.Exhibitor;
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 com.example.guitarista.citem.R;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
*/
public class TabInternationalFragment extends Fragment {
private List<Exhibitors_Int> items;
private RecyclerView rv;
public TabInternationalFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_exhibitor_tab_international, container, false);
rv=(RecyclerView)v.findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
//GridLayoutManager glm = new GridLayoutManager(getActivity(), 4);
//rv.setLayoutManager(glm);
rv.setHasFixedSize(true);
initializeData();
initializeAdapter();
return v;
}
private void initializeData() {
items = new ArrayList<>();
items.add(new Exhibitors_Int("A. GARCIA CRAFTS", "FURNITURE", R.drawable.image1));
items.add(new Exhibitors_Int("BALEX BOXES", "HOLIDAY DECORATION", R.drawable.image2));
items.add(new Exhibitors_Int("CAGAYAN DE ORO HANDMADE PAPER", "HOME DECOR/HOUSEWARE", R.drawable.image3));
}
private void initializeAdapter(){
TabInt_RV_Adapter adapter = new TabInt_RV_Adapter(items, getContext());
rv.setAdapter(adapter);
}
}
If you want to keep your first activity as it was after you've pressed the back button, you should define the launch mode of your first activity in the AndroidManifest.xml. Also define the parent activity for your second activity, so Android knows which activity it should navigate back to when you press the back button.
<activity
android:name=".activity.HomeActivity"
android:label="#string/app_name"
android:launchMode="singleTop" />
<activity
android:name=".activity.GalleryActivity"
android:label="#string/app_name"
android:parentActivityName=".activity.HomeActivity"
tools:ignore="UnusedAttribute">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.HomeActivity" />
</activity>
The singleTop launch mode will make sure that no new instance of that activity will be created if there is already an instance in the activity stack. So your cards will still be visible in your first activity after pressing the back button.
Related
Using Android's Studio I started with a Navigation Drawer activity. Then I added a Master Detail activity making a "real" class from the DummyContent class template. The application works when hard coding the items. My needs are to use multiple languages so I must use strings.xml for the language translations.
I extended ProductsAZ.java using Activity trying unsuccessfully to use "this" and "getString()". I can assign String header1 = getString(R.string.header1);. How do I use this design/class to call strings from strings.xml when adding a new Product item?
addItem(new Product("1", "1_Title_here", "1_Header_here", "1_Body_here"));
addItem(new Product("2", "2_Title_here", "2_Header_here", "2_Body_here"));
addItem(new Product("3", "3_Title_here", "3_Header_here", "3_Body_here"));
Desire is:
addItem(new Product("1", "#string/1_Title_here", "#string/1_Header_here", "#string/1_Body_here"));
ProductAZ.java
import android.app.Activity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ProductAZ extends Activity {
// An array of items.
// public static List<Product> ITEMS = new ArrayList<>();
public static List<Product> ITEMS = new ArrayList<>();
// A map of items, by ID.
public static Map<String, Product> ITEM_MAP = new HashMap<>();
// Add items.
static {
addItem(new Product("1", "1_Title_here", "1_Header_here", "1_Body_here"));
addItem(new Product("2", "2_Title_here", "2_Header_here", "2_Body_here"));
addItem(new Product("3", "3_Title_here", "3_Header_here", "3_Body_here"));
}
private static void addItem(Product product) {
ITEMS.add(product);
ITEM_MAP.put(product.id, product);
}
// An item representing a piece of content.
public static class Product {
public final String id;
public final String title;
public final String header;
public final String details;
public Product(String id, String title, String header, String details) {
this.id = id;
this.title = title;
this.header = header;
this.details = details;
}
#Override
public String toString() {
return title;
}
}
}
ProductListActivity.java
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import java.util.List;
/**
* An activity representing a list of Products. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {#link ProductDetailActivity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
*/
public class ProductListActivity extends AppCompatActivity {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
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();
}
});
// Show the Up button in the action bar.
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
View recyclerView = findViewById(R.id.product_list);
assert recyclerView != null;
setupRecyclerView((RecyclerView) recyclerView);
if (findViewById(R.id.product_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private void setupRecyclerView(#NonNull RecyclerView recyclerView) {
recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(ProductAZ.ITEMS));
}
public class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final List<ProductAZ.Product> mValues;
public SimpleItemRecyclerViewAdapter(List<ProductAZ.Product> items) {
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.product_list_content, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).title);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ProductDetailFragment.ARG_ITEM_ID, holder.mItem.id);
ProductDetailFragment fragment = new ProductDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.product_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, ProductDetailActivity.class);
intent.putExtra(ProductDetailFragment.ARG_ITEM_ID, holder.mItem.id);
context.startActivity(intent);
}
}
});
}
#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 ProductAZ.Product 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() + "'";
}
}
}
}
ProductDetailFragment.java
import android.app.Activity;
import android.support.design.widget.CollapsingToolbarLayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* A fragment representing a single Product detail screen.
* This fragment is either contained in a {#link ProductListActivity}
* in two-pane mode (on tablets) or a {#link ProductDetailActivity}
* on handsets.
*/
public class ProductDetailFragment extends Fragment {
/**
* The fragment argument representing the item ID that this fragment
* represents.
*/
public static final String ARG_ITEM_ID = "item_id";
// The content this fragment is presenting.
// private ProductAZ.Product mItem;
private ProductAZ.Product mProduct;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ProductDetailFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments().containsKey(ARG_ITEM_ID)) {
// Load the content specified by the fragment
// arguments. In a real-world scenario, use a Loader
// to load content from a content provider.
mProduct = ProductAZ.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
Activity activity = this.getActivity();
CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout);
if (appBarLayout != null) {
appBarLayout.setTitle(mProduct.title);
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.product_detail, container, false);
// Show the content as text in a TextView.
if (mProduct != null) {
((TextView) rootView.findViewById(R.id.product_detail)).setText(mProduct.details);
}
return rootView;
}
}
ProductDetailActivity.java
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.NavUtils;
import android.view.MenuItem;
/**
* An activity representing a single Product detail screen. This
* activity is only used narrow width devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a {#link ProductListActivity}.
*/
public class ProductDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.detail_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 detail action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
// Show the Up button in the action bar.
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don't need to manually add it.
// For more information, see the Fragments API guide at:
//
// http://developer.android.com/guide/components/fragments.html
//
if (savedInstanceState == null) {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(ProductDetailFragment.ARG_ITEM_ID,
getIntent().getStringExtra(ProductDetailFragment.ARG_ITEM_ID));
ProductDetailFragment fragment = new ProductDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.product_detail_container, fragment)
.commit();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpTo(this, new Intent(this, ProductListActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
product_detail.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/product_detail"
style="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:textIsSelectable="true"
tools:context="com.bobh.znd6.ProductDetailFragment"/>
product_list.xml (small display)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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:id="#+id/product_list"
android:name="com.bobh.znd5.ProductListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="com.bobh.znd6.ProductListActivity"
tools:listitem="#layout/product_list_content"/>
product_list_content.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"/>
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"/>
</LinearLayout>
Solved. I found the solution in link. I needed to delete my switch statement in ProductAZ.java. Then in DetailListActivity.java I edited the onCreate method. Using the prior post's outline fitting my class/method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DummyContent.ITEMS.isEmpty())
{
DummyContent.addItem(new DummyItem("1", getResources().getString(R.string.menu1)));
DummyContent.addItem(new DummyItem("2", getResources().getString(R.string.menu2)));
DummyContent.addItem(new DummyItem("3", getResources().getString(R.string.menu3)));
}
I am not sure how to ask this. I tried in here, but I guess I was not clear enough. So, I thought I just write a small App to describe the situation. Please note, the App uses Googles SlidingTabLayout.
Long story short, at any point if I click Button1, the FrameLayout should contain Fragment1, removing Fragment2 (if exists). Therefore, FragmentViewPager should also be destroyed as Fragment2. However, even then if I change the orientation of my device, I get the Toast which is defined in the onCreate() method of FragmentViewPager.
Why FragmentViewPager's onCreate is called even if Fragment2 is paused/destroyed? Is it possible that, the Toast of FragmentViewPager will not be shown when Fragment2 is destroyed?
MainActivity:
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(onClickListener);
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(onClickListener);
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment;
switch (v.getId()){
case R.id.button1:
fragment = new Fragment1();
break;
case R.id.button2:
fragment = new Fragment2();
break;
default:
return;
}
getFragmentManager().beginTransaction().replace(R.id.frame_container, fragment, v.getTag().toString()).addToBackStack(null).commit();
}
};
}
Fragment1
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment {
public Fragment1(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment1,container,false);
setHasOptionsMenu(true);
return rootView;
}
}
Fragment2
package com.abdfahim.testproject;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment2 extends Fragment {
public Fragment2(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment2,container,false);
setHasOptionsMenu(true);
CharSequence titles[]= {"Tab A", "Tab B"};
// Creating The ViewPagerAdapter
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getFragmentManager(), titles, titles.length);
ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assigning the Sliding Tab Layout View
SlidingTabLayout tabs = (SlidingTabLayout) rootView.findViewById(R.id.tabs);
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
return rootView;
}
static class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence titles[];
private int numbOfTabs;
public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabs) {
super(fm);
this.titles = mTitles;
this.numbOfTabs = mNumbOfTabs;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putString("displayText", "Inside Fragment 2, " + titles[position]);
FragmentViewPager fragment = new FragmentViewPager();
fragment.setArguments(bundle);
return fragment;
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return numbOfTabs;
}
}
}
FragmentViewPager
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
public class FragmentViewPager extends Fragment {
public FragmentViewPager(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_view_pager,container,false);
setHasOptionsMenu(true);
Bundle bundle = this.getArguments();
TextView textView = (TextView) rootView.findViewById(R.id.tabText);
textView.setText(bundle.getString("displayText"));
return rootView;
}
#Override
public void onStart() {
super.onStart();
Toast.makeText(getActivity(), "This is View Pager Fragment", Toast.LENGTH_SHORT).show();
}
}
when you use fragment inside another fragment. you use getChildFragmentManager() instead of getFragmentManager. You can call setAdapter() for the ViewPager from onCreateView() or onActivityCreated()
for more detail. have a look at it
Why it is not possible to use ViewPager within a Fragment? It actually is
For every click your OnClickListener creates the instance of Fragment2 and does not create Fragment1. That is due to the misuse of View#getTag.
In MainActivity#onCreate, change the if in the definition of onClickListener to this(using this answer):
switch (v.getId()){
case R.id.button1:
fragment = new Fragment1();
break;
case R.id.button2:
fragment = new Fragment2();
break;
default:
return;
}
In your code, in the if that is checked upon a click (for example after clicking button1) android asks v (the clicked View) for its tag - but as none was set using View#setTag - it returns null which is of course not equal to the String object created for "button1", thus the if reverts to the else every time.
Here is the code of MainActivity which I have written.
I am loading the list of fragment in the first screen. When the user taps on any of the list items, the planet name will be shown to the user in the detail fragment which I have defined in a separate class.
I am adding the transaction of "Fragment Planet List" -> "Fragment Planet Detail" to back stack. So what I expect is when I press the back button from the fragment of planet detail, it should load planet list in the phone. But it is not happening this way.
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.FrameLayout;
import com.meditab.fragments.fragment.FragmentPlanetDetail;
import com.meditab.fragments.fragment.FragmentPlanetList;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends ActionBarActivity implements Callback {
private FrameLayout frmPlanetList;
private FrameLayout frmPlanetDetail;
private boolean isPhone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frmPlanetList = (FrameLayout) findViewById(R.id.frmPlanetList);
frmPlanetDetail = (FrameLayout) findViewById(R.id.frmPlanetDetail);
if (null != frmPlanetDetail) {
isPhone = false;
} else {
isPhone = true;
}
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frmPlanetList, new FragmentPlanetList());
fragmentTransaction.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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);
}
#Override
public void onListItemClicked(int intPosition) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
List<String> lstPlanetArray = getPlanetArray();
String strPlanetName = lstPlanetArray.get(intPosition);
FragmentPlanetDetail fragmentPlanetDetail = FragmentPlanetDetail.newInstance(strPlanetName);
if (isPhone) {
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.frmPlanetList, fragmentPlanetDetail);
} else {
fragmentTransaction.replace(R.id.frmPlanetDetail, fragmentPlanetDetail);
}
fragmentTransaction.commit();
}
private List<String> getPlanetArray() {
List<String> lstPlanets = new ArrayList<>(10);
lstPlanets.add("Mercury");
lstPlanets.add("Venus");
lstPlanets.add("Earth");
lstPlanets.add("Mars");
lstPlanets.add("Jupiter");
lstPlanets.add("Saturn");
lstPlanets.add("Uranus");
lstPlanets.add("Neptune");
lstPlanets.add("Saturn");
return lstPlanets;
}
}
However if I override the backPress method and pop the back stack programatically, it works just fine.
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() != 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Do I need to override the onBackPressed() method this way if I want to achieve this behavour?
It is not documented that you need to override this method in this link.Android Back Press Fragment Documentation
Fragment Planet Detail Class
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.meditab.fragments.R;
/**
* Created by BHARGAV on 25-Dec-14.
*/
public class FragmentPlanetDetail extends Fragment {
private String strPlanetName;
public FragmentPlanetDetail() {
}
public static FragmentPlanetDetail newInstance(String strPlanetName) {
FragmentPlanetDetail fragmentPlanetDetail = new FragmentPlanetDetail();
Bundle bundle = new Bundle();
bundle.putString("Planet_Name", strPlanetName);
fragmentPlanetDetail.setArguments(bundle);
return fragmentPlanetDetail;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if (null != bundle) {
strPlanetName = bundle.getString("Planet_Name");
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.planet_name, container, false);
TextView txtPlanetName = (TextView) rootView.findViewById(R.id.txtPlanetName);
txtPlanetName.setText(strPlanetName);
return rootView;
}
}
Fragment Planet List Class:
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.meditab.fragments.Callback;
import com.meditab.fragments.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by BHARGAV on 25-Dec-14.
*/
public class FragmentPlanetList extends Fragment {
private ListView listView;
private ArrayAdapter<String> stringArrayAdapter;
private Callback callback;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.listview, container, false);
listView = (ListView) rootView.findViewById(R.id.listView);
stringArrayAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_list_item_1, getPlanetArray());
listView.setAdapter(stringArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
callback.onListItemClicked(position);
}
});
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (Callback) activity;
}
private List<String> getPlanetArray() {
List<String> lstPlanets = new ArrayList<>(5);
lstPlanets.add("Mercury");
lstPlanets.add("Venus");
lstPlanets.add("Earth");
lstPlanets.add("Mars");
lstPlanets.add("Jupiter");
lstPlanets.add("Saturn");
lstPlanets.add("Uranus");
lstPlanets.add("Neptune");
lstPlanets.add("Saturn");
return lstPlanets;
}
}
Callback Interface:
/**
* Created by BHARGAV on 26-Dec-14.
*/
public interface Callback {
public void onListItemClicked(int intPosition);
}
Thanks. Please let me know if any additional detail or code is needed.
Ok. So the reason why it is not working is the conflict of ActionBarActivty and Activity class differences.
And the differnce between getSupportFragmentManager() and getFragmentManager() methods of FragmentTransaction.
ActionBarActivity:
I was using ActionBarActivity which is android.support.v7.app.ActionBarActivity. This means I was using v7 compat library
FragmentManager:
Fragment Manager were not from the compat library. It was directly
import android.app.FragmentManager;
import android.app.FragmentTransaction;
as you can see in the MainActivity class.
Fragment:
android.app.Fragment; is the class which is imported in the separate fragment classes.
So once I changed from ActionBarActivity to Activity class, things were working fine.
The same holds true when I changed the FragmentManager,FragmentTransaction and Fragment classes to support library classes.
So after any of the modification, things started working normally.
Thanks.
Of course you don't need to override the onBackPressed() method. It's just a hack.
Your this condition is messing it up.
if (isPhone) {
fragmentTransaction.addToBackStack(null);
why don't you use this statement without condition once to see if it works. You can keep rest as it is. Just move this statement outside of the if condition.
Wierd, but I think
addToBackStack(null)
is the problem
Try replcing it with
addToBackStack("planetDetail");
You are using actionbar activity which extends fragment activity. Now, to have perfect behaviour, you need support fragments to work with actionbar activity.
Here you are using actionbar activity with normal fragments (not support v4 fragments) and that's what is causing the issue. So to have perfect behaviour, change your fragments to support fragments and it should work fine.
Let me know if that doesn't work.
Well I was having the same problem with you. What worked for me and I think its the solution for you too is to change the :
1.fragment with the fragment from the support library :
import android.support.v4.app.Fragment;
and
getFragmentManager() with the getSupportFragmentManager() :
I have created a navigation drawer for my app from androidhive.info. In that navigation drawer, in one fragment, I have created a custom listview which shows the elements with a name and image. Now upon clicking an item of the custom listview, I need to show the details of the clicked list element. For that I have created another fragment. Now upon clicking the listview element, I should move onto the details of the selected element. The code which I have used for moving from one fragment to another is this:
Fragment fragment=new ImportantNumbersFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
But the getSupportFragmentManager() is showing an error in eclipse like this: The method getSupportFragmentManager() is undefined for the type PagesFragment. This is the code of my custom listview fragment.
PagesFragment.class
public class PagesFragment extends ListFragment implements OnItemClickListener{
Typeface tf;
ListView lv;
List<SimpleRow>rowItems;
public PagesFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_pages, container, false);
Helper help=new Helper(getActivity().getApplicationContext());
String choice1="സര്ക്കാര് സ്ഥാപനങ്ങള്";
String choice1new=help.changemalayalam(new Data(choice1));
String choice2="പത്രം";
String choice2new=help.changemalayalam(new Data(choice2));
String choice3="ന്യൂസ് ചാനല്";
String choice3new=help.changemalayalam(new Data(choice3));
String choice4="യൂണിവേഴ്സിറ്റികള്";
String choice4new=help.changemalayalam(new Data(choice4));
String choice5="പഞ്ചായത്ത് ഓഫീസ്";
String choice5new=help.changemalayalam(new Data(choice5));
String choice6="ഇന്ഷുറന്സ്";
String choice6new=help.changemalayalam(new Data(choice6));
String choice7="പോലീസ് സ്റ്റേഷന്";
String choice7new=help.changemalayalam(new Data(choice7));
String choice8="ഫയര് സ്റ്റേഷന്";
String choice8new=help.changemalayalam(new Data(choice8));
ArrayList<String>choice=new ArrayList<String>();
choice.add(choice1new);
choice.add(choice2new);
choice.add(choice3new);
choice.add(choice4new);
choice.add(choice5new);
choice.add(choice6new);
choice.add(choice7new);
choice.add(choice8new);
lv=(ListView)rootView.findViewById(R.id.list1);
rowItems=new ArrayList<SimpleRow>();
for (int i = 0; i < choice.size(); i++) {
SimpleRow item = new SimpleRow(choice.get(i));
rowItems.add(item);
CustomSimpleListAdapter adapter = new CustomSimpleListAdapter(getActivity().getApplicationContext(),R.layout.list_single, rowItems);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
}
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Toast.makeText(getActivity().getApplicationContext(), "You clicked on position "+position,Toast.LENGTH_LONG).show();
//Here upon clicking the list element, I need to go to ImportantNubersFragment
Fragment fragment=new ImportantNumbersFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Toast.makeText(getActivity().getApplicationContext(), "You clicked on position "+arg2,Toast.LENGTH_LONG).show();
}
}
ImportantNumbersFragment.class
public class ImportantNumbersFragment extends Fragment {
public ImportantNumbersFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_container, container, false);
return rootView;
}
}
fragment_important_numbers.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout android:name="fragments.YourInitialFragment"
android:id="#+id/fragment_container"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" />
</LinearLayout>
I want to move from PagesFragment to ImportantNumbersFragment upon clicking the list element in the custom listview. So in the OnListItemClick, I have given the code for moving from fragment to another. I have to do this in the sameway as that of moving from one activity to another activity using intents like:
Intent i=new Intent(First.this,Second.class);
startActivity(i);.
Since I'm new to fragments, I don't know how this can be achieved in fragments. That's why I have asked here. Can someone please point out the errors in this code. Thanks in advance..
Are you using Support package for fragment in all extended Fragment
Classes, Check !
.
I myself have used the code from AndroidHive and it works perfectly
.
There it does not uses Support package for extended fragment classes
.
Somewhere in code you are using a Support import, Make sure you
maintain uniformity among imports
.
Programatically Speaking for ex::
If you are using support package use codes like these
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
If you are not using support package use codes imports ::
import android.app.ActionBarDrawerToggle;
import android.app.Fragment;
import android.app.FragmentActivity;
import android.app.FragmentTransaction;
import android.widget.DrawerLayout;
{EDIT - Sample on how one of the way to perform fragment transaction}
MainActivity.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
public class MainActivity extends FragmentActivity {
Fragment fragment;
String className;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d("MainActivity", "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Store the name of the class
className=MainActivity.class.getSimpleName();
//First fragment should be mounted on oncreate of main activity
if (savedInstanceState == null) {
/*fragment=FragmentOne.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(className).commit();
*/
Fragment newFragment = FragmentOne.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, newFragment).addToBackStack(null).commit();
Log.d("FRAGMENT-A", "fragment added to backstack");
}
}
}
FragmentOne.java
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.Spinner;
import com.sample.screennavigation.UtilRangeSeekBar.OnRangeSeekBarChangeListener;
public class FragmentOne extends Fragment{
//Declare variables that hold the data for configuration change
public static FragmentOne newInstance(){
Log.d("FragmentOne", "newInstance");
FragmentOne fragment = new FragmentOne();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("FragmentOne", "onCreateView");
View view=inflater.inflate(R.layout.fragment_one, container, false);
return view;
}
}
{EDIT-2}
PagesFragment ... is using a support package somewhere, check
it !
Check imports of pagefragment
But the getSupportFragmentManager() is showing an error in eclipse like this: The method getSupportFragmentManager() is undefined for the type PagesFragment.
Error in your code clearly says you are using a supportpackage import
and it is conflicting the execution
Rememmber you cannot mix the imports
Hope it helps !, let me know if you need any additional info
I have this fragment that inflates an activity with buttons. How do I make the buttons go to another activity or fragment? the button 1 is supposed to go to a map activity and the button 2 a listfragment
EDIT**
All I want is one activity with 2 buttons and one of the buttons go to a fragment
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
static Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//context = getApplicationContext();
Button test= (Button)findViewById(R.id.testbtn);
test.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this, MyLocation.class);//this works
startActivity(intent);
}
});
Button proximityAlert= (Button)findViewById(R.id.alertbtn);
proximityAlert.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this, mfragment.class);//this doesn't work, this class is a fragment list
startActivity(intent);
}
});
}
#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;
}
}
mfragment class
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.support.v4.app.ListFragment;
public class mfragment extends ListFragment {
String[] cities = {
"hello",
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setting the adapter to the layout
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1,
cities));
}
public void onListItemClick(ListView parent, View v, int position, long id) {
//displays a toest of the selected item in the list
//using an array to and using the position of the selected item
Toast.makeText(getActivity(),
"You have selected " + cities[position],
Toast.LENGTH_SHORT).show();
String selectedCity = cities[position];
/*//cheks if the detailfragment is in the current activity
DetailFragment detailFragment = (DetailFragment)
getFragmentManager().findFragmentById(R.id.detailFragment);
//---if the detail fragment is not in the current activity as myself---
if (detailFragment != null && detailFragment.isInLayout()) {
//---the detail fragment is in the same activity as the master---
detailFragment.setSelectedCity(selectedCity);
//calls the method set selected city and sends a string with the selcted city
} else {
*/
//---the detail fragment is in its own activity---
//this is only needed if is in portrait mode
//starts a new activity and it pass arguments to know
//which city got selected
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra("city", selectedCity);
startActivity(intent);
//}
}
}
You need to specify the buttons in the correct layouts. If you want one button to be in the activity, you need to specify it in the activity's layout xml file. You will then use it from the activity's code. Likewise, you need to specify the button you want to be in the fragment in the fragment's xml layout file.
You cannot mix the layouts from activity and fragment, each one functions independent of each other and doesn't have direct access to each other.
I'm sorry to say this, but you are way far from what you want. Check this example: http://developer.android.com/guide/components/fragments.html#Example