Add a fragment to activity its not working - android

Im studying about fragments and Im doing a basic example but its not working.
I have a basic example where I have 2 activities:
- One activity with a image and a textview and when the image is clicked I go to another activity that that has a list view with some items. When this list view is clicked I go back to the main activity and in the textview I show the text associated with the list item clicked.
But Now Im trying to pass this basic example but using fragments with only one activity, but its not working it appears always “app has stopped” when the image is clicked.
What Im doing, and I don’t know if its the best solution, is have the main activity just with the image that needs to be clicked so that it appears the fragment with the list view. And having 2 fragments, one to show the list view and another to show the textview with the text of the clicked item.
For now im just doing the first part, that is click on the image and show the fragment with the list view and when the item on the fragment is clicked show a message with toast. But its not working, it appears always “app has “stopped”.
So what I have is, in the main activity:
public class MainActivity extends AppCompatActivity {
private ImageView img;
private TextView tv;
Intent intent;
FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getFragmentManager();
img = (ImageView) findViewById(R.id.imageView);
tv = (TextView) findViewById(R.id.textView);
}
public void AddFragmentList(View view) {
Fragment fragment = new Fragment();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.listviewInFragment, fragment, "frag");
transaction.commit();
}
}
main activity xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/image"
android:onClick="AddFragmentList"
tools:layout_editor_absoluteY="71dp"
tools:layout_editor_absoluteX="0dp" />
<FrameLayout
android:layout_width="0dp"
android:layout_height="11dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="110dp">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
In fragment java:
public class fragment extends Fragment {
private ListView listItems;
private String[] items = {
"item1",
"item2",
"item3",
"item4"
};
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listItems = (ListView) listItems.findViewById(R.id.listviewInFragment);
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(getActivity().getApplicationContext(),
android.R.layout.simple_list_item_1, android.R.id.text1, items);
listItems.setAdapter(adapter);
listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int positionCode = i;
String clickedValue = (String) listItems.getItemAtPosition(positionCode);
Listener listener = (Listener) getActivity();
listener.addText(clickedValue);
Toast.makeText(getActivity().getApplicationContext(), clickedValue, Toast.LENGTH_SHORT).show();
}
});
}
}
And in fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0ff">
<ListView
android:layout_width="368dp"
android:layout_height="495dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="16dp"
android:id="#+id/listviewInFragment"/>
</android.support.constraint.ConstraintLayout>

Have a id for FrameLayout
<FrameLayout
andorid:id="#+id/container"
android:layout_width="0dp"
Then change
transaction.add(R.id.listviewInFragment, fragment, "frag");
to
transaction.add(R.id.container, new fragment(), "frag");
Finally change this
listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int positionCode = i;
String clickedValue = (String) listItems.getItemAtPosition(positionCode);
Listener listener = (Listener) getActivity();
listener.addText(clickedValue);
Toast.makeText(getActivity().getApplicationContext(), clickedValue, Toast.LENGTH_SHORT).show();
}
to
listItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String clickedValue = (String) adapterView.getItemAtPosition(i);
Toast.makeText(getActivity().getApplicationContext(), clickedValue, Toast.LENGTH_SHORT).show();
}
Besides you can have interface as a callbaclk to the activity. Not sure what you are doing with Listener listener = (Listener) getActivity();listener.addText(clickedValue);
This should help https://developer.android.com/training/basics/fragments/communicating.html

Related

How to used a shared transition from RecyclerView to a Fragment

I've seen this questioned asked a number of times on here without an answer. I'm hoping if I ask it again maybe someone will be kind enough to help me with it.
I'm trying to implement a shared transition from an Item in a Recyclerview to a fragment.
I currently have my fragment transaction in the onBindView method of the adapter.
public void onClick(View v) {
...
activity.getSupportFragmentMnager().beginTransaction()
.addSharedElement(v, "SharedString")
.replace(R.id.container, fragment2)
.addToBackStack(null)
.commit();
}
In the android docs, addSharedElement(view and string) confuse me. How do I give the view a unique ID and should I even be using v here?
Can the string be what ever I want?
here is my implementation. There is FragmentList with RecyclerView with images on each item. And there is FragmentDetail with only on big image. Image from FragmentList list item fly to FragmentDetail. TransitionName of animated view on FragmentList and FragmentDetail must be same. So I give unique transition name for each list item ImageView:
imageView.setTransitionName("anyString" + position)
Then I pass that string to FragmentDetail via setArguments and set big image transitionName to that string. Also we should provide Transition which describes how view from one view hierarchy animates to another viewhierarchy. After that we should pass that transition to fragment. I do it before FragmentTransaction:
detailFragment.setSharedElementEnterTransition(getTransition());
detailFragment.setSharedElementReturnTransition(getTransition());
Or you can override getSharedElementEnterTransition and getSharedElementReturnTransition of Fragment and declare transition there. Here is full code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new FragmentList())
.commit();
}
}
public void showDetail(View view) {
String transitionName = view.getTransitionName();
FragmentDetail fragment = new FragmentDetail();
fragment.setArguments(FragmentDetail.getBundle(transitionName));
fragment.setSharedElementEnterTransition(getTransition());
fragment.setSharedElementReturnTransition(getTransition());
getSupportFragmentManager()
.beginTransaction()
.addSharedElement(view, transitionName)
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
}
private Transition getTransition() {
TransitionSet set = new TransitionSet();
set.setOrdering(TransitionSet.ORDERING_TOGETHER);
set.addTransition(new ChangeBounds());
set.addTransition(new ChangeImageTransform());
set.addTransition(new ChangeTransform());
return set;
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
FragmentList:
public class FragmentList extends Fragment {
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.fragment_list, container, false);
RecyclerView rv = view.findViewById(R.id.recyclerview);
rv.setAdapter(new ListAdapter());
return view;
}
private class ListAdapter extends RecyclerView.Adapter {
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new Holder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Holder hold = (Holder) holder;
hold.itemView.setOnClickListener(v -> {
((MainActivity) getActivity()).showDetail(hold.imageView);
});
//unique string for each list item
hold.imageView.setTransitionName("anyString" + position);
}
#Override
public int getItemCount() {
return 10;
}
private class Holder extends ViewHolder {
ImageView imageView;
public Holder(View view) {
super(view);
imageView = view.findViewById(R.id.image);
}
}
}
}
fragment_list.xml
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
FragmentDetail:
public class FragmentDetail extends Fragment {
private static final String NAME_KEY = "key";
public static Bundle getBundle(String transitionName) {
Bundle args = new Bundle();
args.putString(NAME_KEY, transitionName);
return args;
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.fragment_detail, container, false);
String transitionName = getArguments().getString(NAME_KEY);
ImageView imageView = view.findViewById(R.id.image);
imageView.setTransitionName(transitionName);
return view;
}
}
fragment_detail.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="#+id/image"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="#drawable/cat"/>
</LinearLayout>
item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="#+id/image"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/cat"/>
</LinearLayout>
Here is result:
TransitionName may be any string you want.
There is ViewCompat.setTransitionName if you need support pre Lollipop devices.
Adding to the ashakirov's answer:
Problem
Return Transition was not working!
Reason:
On popbackstack from Fragment B to Fragment A, Fragment A's onCreateView is called and if your data is still loading then the return transition won't work with only ashakirov's code.
Solution
Postpone the transition in your fragments
Add this line where the loading starts in your fragment A:
postponeEnterTransition();
After your data is loaded or you've set your adapter, write this:
startPostponedEnterTransition();
This ensures that your transition only happens after your data is loaded.
Also, make sure you start the transition even in 'data failed to load scenarios'.
If you want to postpone the transition in your fragment B when going from A to B then add this to your fragment B:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//hold the transition
postponeEnterTransition();
//when the views are available then start the transition
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return true;
}
});
}

Change Fragment on setOnItemClickListener to ListView with CardView

I have a ListView that uses a CardView to inflate it's layout. When the user clicks on the the first item in the ListView, this should change the Fragment. However, I am unsure of how to do this. I attempted to change the Fragment in the adapter class (CustomAdapter.java) and it didn't work. I also have tried doing this in the Fragment the ListView is in but it didn't work either (the app didn't crash when I clicked one of the items - nothing happened):
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new DesignsWorkshopFragment();
break;
}
if (fragment != null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
});
SuppliersFragment.java:
public class SuppliersFragment extends Fragment {
CustomAdapter adapter;
ListView lv;
public SuppliersFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_suppliers, container, false);
lv = view.findViewById(R.id.lvFragmentSuppliers);
adapter = new CustomAdapter(getContext(), getData());
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new DesignsWorkshopFragment();
break;
}
if (fragment != null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
});
return view;
}
private ArrayList getData() {
ArrayList<SuppliersCardview> suppliersCardview = new ArrayList<>();
SuppliersCardview s = new SuppliersCardview();
s.setThumbnail(R.drawable.designs_workshop_logo);
s.setName("Designs Workshop");
suppliersCardview.add(s);
s = new SuppliersCardview();
s.setThumbnail(R.drawable.organic_clothing_logo);
s.setName("Organic Clothing Industries");
suppliersCardview.add(s);
s = new SuppliersCardview();
s.setThumbnail(R.drawable.suns_sewing_ltd);
s.setName("Sun's Sewing Ltd");
suppliersCardview.add(s);
return suppliersCardview;
}}
CustomAdapter.java:
public class CustomAdapter extends BaseAdapter {
Context c;
ArrayList<SuppliersCardview> suppliersCardview;
public CustomAdapter(Context c, ArrayList<SuppliersCardview> suppliersCardview) {
this.c = c;
this.suppliersCardview = suppliersCardview;
}
#Override
public int getCount() {
return suppliersCardview.size();
}
#Override
public Object getItem(int position) {
return suppliersCardview.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(c).inflate(R.layout.cardview_layout, parent, false);
}
final SuppliersCardview s = (SuppliersCardview) this.getItem(position);
ImageView imageView = convertView.findViewById(R.id.ivSupplierLogo);
TextView textView = convertView.findViewById(R.id.tvSupplierName);
imageView.setImageResource(s.getThumbnail());
textView.setText(s.getName());
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Attempted to change fragment here in a switch statement
}
});
return convertView;
}
SuppliersCardview.java:
public class SuppliersCardview {
private String name;
private int thumbnail;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getThumbnail() {
return thumbnail;
}
public void setThumbnail(int thumbnail) {
this.thumbnail = thumbnail;
}}
SuppliersFragment XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.miguelpeachey.marketplacesimulator.Fragments.SuppliersFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/tvBrowseSuppliersHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#bfbdbd"
android:fontFamily="#font/nunito_sans"
android:paddingBottom="5dp"
android:paddingStart="10dp"
android:paddingTop="10dp"
android:text="Browse Suppliers"
android:textSize="25sp" />
<ListView
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:id="#+id/lvFragmentSuppliers"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/colorTransparent"
android:dividerHeight="20dip"/>
</LinearLayout>
CardView XML:
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="40dp"
android:orientation="vertical"
app:cardPreventCornerOverlap="false"
app:ignore="NamespaceTypo"
card_view:cardBackgroundColor="#cccbcb"
card_view:cardCornerRadius="15dp"
card_view:cardElevation="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/ivSupplierLogo"
android:layout_width="150dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:src="#drawable/ic_launcher_background" />
<TextView
android:id="#+id/tvSupplierName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/ivSupplierLogo"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:fontFamily="#font/brawler"
android:text="Supplier"
android:textColor="#232323"
android:textSize="22sp" />
</RelativeLayout>
So how can I replace/change fragments on the ListView's item click that uses a CardView as its layout? Other people's solutions did not help me.
I have used this website as a tutorial to create the CardView and inflate the ListView's layout (some code here is from the website).
You have your object of fragment now you need to use fragment manager and replace existing fragment with fragment you want to show.
DesignsWorkshopFragment fragment2=new DesignsWorkshopFragment();
FragmentManager fragmentManager=getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_main,fragment2,"tag");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Only creating your fragment's instance will not show it in activity.
Adding and replacing of fragment is done inside activity.You need to notify your activity on the click of item view in your ListView.This can be done using interfaces.
create one interface:
public interface ClickListener{
public void onClick();
}
Implement this interface in your activity.And when you are creating the Fragment pass "this" as reference inside fragment's constructor.Like this :
fragment = new DesignsWorkshopFragment(this);
Inside fragment, you need to create the interface reference.
private ClickListener clickListener ;
Inside fragment initialize this interface reference
DesignsWorkshopFragment(ClickListener clickListener){
this.clickListener = clickListener;
}
Now do the same thing when you are creating adapter.
adapter = new CustomAdapter(getContext(), getData(),clickListener);
Inside adapter create and intialize interface reference.
private ClickListener clickListener ;
public CustomAdapter(Context c, ArrayList<SuppliersCardview> suppliersCardview,
ClickListener clickListener ) {
this.c = c;
this.suppliersCardview = suppliersCardview;
this.clickListener = clickListener;
}
and whenever a click is happening. just call the interface method.
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clickListener.onClick();
}
});
this will give a callback inside your activity's interfcae implementation. In here
public void onClick(){
//write your code for adding or replacing fragment.
}
I managed to get this working by just removing
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
in my CustomAdapter.java class.

Layout for tablets using two fragments

I am doing a sample project as an excercise and want to display two fragments in the same activity when dealing with tablets(7' and 10').
So what I have so far is this.
As you can see I can display the data of my recyclerview in the left (static) fragment. However the right fragment is empty.
So I have two questions.
1) How to display by default in the right fragment the data of the first row of recyclerview?(ie image and article)
2) How to implement the click listener and update the right fragment?
Here is my code:
MainActivity
public class MainActivity extends AppCompatActivity {
private boolean mTwoPane;
private static final String DETAIL_FRAGMENT_TAG = "DFTAG";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(findViewById(R.id.detailed_match_reports)!=null) {
mTwoPane = true;
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.detailed_match_reports, new DetailedActivityFragment(),DETAIL_FRAGMENT_TAG)
.commit();
}else{
mTwoPane = false;
}
}
}
}
layout/activity_main.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/match_reports"
android:name="theo.testing.androidservices.fragments.MainActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context="theo.testing.androidservices.activities.MainActivity"
tools:layout="#android:layout/list_content" />
layout-sw600dp/activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
tools:context="theo.testing.androidservices.activities.MainActivity">
<fragment
android:id="#+id/match_reports"
android:name="theo.testing.androidservices.fragments.MainActivityFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
tools:layout="#android:layout/list_content" />
<FrameLayout
android:id="#+id/detailed_match_reports"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="4" />
</LinearLayout>
MainActivityFragment
public class MainActivityFragment extends Fragment {
public static final String TAG = "AelApp";
public static ArrayList<MyModel> listItemsList;
RecyclerView myList;
public static MatchReportsAdapter adapter;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateMatchReport();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
getActivity().setTitle("Match Report");
View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false);
listItemsList = new ArrayList<>();
myList = (RecyclerView)rootView.findViewById(R.id.listview_match_reports);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
myList.setHasFixedSize(true);
myList.setLayoutManager(linearLayoutManager);
adapter = new MatchReportsAdapter(getActivity(), listItemsList);
myList.setAdapter(adapter);
return rootView;
}
public void updateMatchReport(){
Intent i = new Intent(getActivity(), MatchReport.class);
getActivity().startService(i);
}
}
First let me answer the second question. To show a fragment on the right side of the screen add something like this (note how I'm using that id of the frame layout to replace the fragment):
Fragment fragment = new MyRightSideFragment();
FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(R.id.detailed_match_reports, fragment).commit();
Now, for the first question, you need to implement click listener, you can find an example here.
public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
showDetail(position);
}
});
}
}
Notice that I'm using the tag of the view to identify the position (so somwhere in your onBindViewHolder code you must set this tag).
public function showDetail(int position) {
... show fragment por position
}
and finally, when your in your OnCreateView or somewhere in your setup code, call showDetail(0).

UnsupportedOperationException: addView(View) is not supported in AdapterView

I looked at existing posts with the same error but code/implementation is different to mine, however the suggestions in some of the posts has not helped to resolve the issue. I am trying to replace a fragment which displays grid (list of images) with another fragment upon an image click. I see the error "Java.lang.UnsupportedOperationException: addView(View) is not supported in AdapterView" during runtime but couldn't make out which part of the code is resulting in this error and what needs to be done to fix this issue. Appreciate your help to resolve this. Code is as below:
Fragment with grid (list of images):
public class OneFragment extends Fragment {
public OneFragment() {
// Required empty public constructor
}
private ListView mListView;
GridView grid;
String[] web = {"Doctors","Dentists","Test" };
int[] imageId = {R.mipmap.doctors,R.mipmap.dentists,R.mipmap.ic_launcher};
#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_one, container, false);
int iconSize=getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
CustomGrid adapter = new CustomGrid(view.getContext(), iconSize);
GridView gridview = (GridView) view.findViewById(R.id.grid);
gridview.setAdapter(adapter);
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(view.getContext(), "You Clicked at " +web[+ position], Toast.LENGTH_SHORT).show();
Log.d("MyApp", "I am here");
//setContentView(R.layout.list_item_main);
ListItemMainFragment nextFrag = new ListItemMainFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.grid, nextFrag);
ft.setTransition(FragmentTransaction.TRANSIT_NONE);// it will anim while calling fragment.
ft.addToBackStack(null); // it will manage back stack of fragments.
ft.commit();
}
});
return view;
}
}
Fragment Resource file:
<GridView
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/grid"
/>
</RelativeLayout>
Fragment for Replacement:
public class ListItemMainFragment extends Fragment implements Item.DataListener {
private ListView mListView;
public ListItemMainFragment() {
// Required empty public constructor
}
#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.list_item_main, container, false);
mListView = (ListView) view.findViewById(R.id.item_list_view);
//final String DBReference = "all/" + position + "/" + web[+position];
final String DBReference = "all/0/Doctors";
Item.getRecipesFromDB(ListItemMainFragment.this, DBReference);
return view;
}
#Override
public void newDataReceived(ArrayList<Item> itemList) {
ItemAdapter adapter = new ItemAdapter(mListView.getContext(), itemList);
mListView.setAdapter(adapter);
}
}
Item List Resource file:
<ListView
android:id="#+id/item_list_view"
android:layout_height="match_parent"
android:layout_width="match_parent">
</ListView>
Do this inside your Fragment Resource file where your grid view is, add an id called content(or any other name) to your Relative layout like thisandroid:id="#+id/content" then in the code where your are doing your fragment replacement, edit this line of code ft.replace(R.id.grid, nextFrag); to be ft.replace(R.id.content, nextFrag);. I was in the same dilemma, this worked for me.
<RelativeLayout>
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/content"
<GridView
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/grid" />
</RelativeLayout>
Java code class OneFragment
ListItemMainFragment nextFrag = new ListItemMainFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, nextFrag);
ft.setTransition(FragmentTransaction.TRANSIT_NONE);// it will anim while calling fragment.
ft.addToBackStack(null); // it will manage back stack of fragments.
ft.commit();

Android. Get listview item onClick inner button to new child fragment

I have a Fragment with a ListView of row items. A row consist in just am ImageView
fragment_1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment1">
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector"/>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip">
<!-- Rightend Play Button. -->
<ImageView
android:id="#+id/play_button"
android:layout_width="50dip"
android:layout_height="50dip"
android:src="#drawable/ic_play"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
I have a ResourceCursorAdapter to fill this ListView. I just assign to each ImageView a click listener. It plays a record saved in the provided path.
private abstract class MyAdapter extends ResourceCursorAadpter {
#Override
public void bindView(View view, Context context, final Cursor cursor) {
// Play button.
ImageView playButton = (ImageView) view.findViewById(R.id.play_button);
playButton.setOnClickListener(new View.OnClickListener() {
String record = cursor.getString(cursor.getColumnIndex(DbAdapter.RECORD));
public void onClick(View v) {
// Play record in path [record]. Not the problem.
}
});
}
}
Now I want to open a new fragment Fragment_2 in a row click. This fragment has the same play_button, and has to play the same record.
fragment_2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_audio"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment2">
<!-- Play Button. -->
<ImageView
android:id="#+id/play_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_play"/>
</RelativeLayout>
How can I manage that this button plays the same record than in Fragment_1? I think I could be able if I have a hidden TextView with the path of the record, but sure you have a smarter solution.
In my onCreateView of Fragment_1.
mList = (ListView) root.findViewById(R.id.list);
// Click event for single row.
mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO: Go to fragment_2 and has the same view [view.findViewById(R.id.play_button)]
}
});
Communication between fragments should be done through the associated Activity. You can use interface for this. it Will serve as contract and bridge between them.
Let's have the following components:
An activity hosts fragments and allow fragments communication
FragmentA first fragment which will send data
FragmentB second fragment which will receive datas from FragmentA
FragmentA's implementation is:
public class FragmentA extends Fragment {
DataPassListener mCallback;
public interface DataPassListener{
public void passData(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Make sure that container activity implement the callback interface
try {
mCallback = (DataPassListener)activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement DataPassListener");
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Suppose that when a button clicked second FragmentB will be inflated
// some data on FragmentA will pass FragmentB
// Button passDataButton = (Button).........
passDataButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (view.getId() == R.id.passDataButton) {
mCallback.passData("Text to pass FragmentB");
}
}
});
}
}
MainActivity implementation is:
public class MainActivity extends ActionBarActivity implements DataPassListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.container) != null) {
if (savedInstanceState != null) {
return;
}
getFragmentManager().beginTransaction()
.add(R.id.container, new FragmentA()).commit();
}
}
#Override
public void passData(String data) {
FragmentB fragmentB = new FragmentB ();
Bundle args = new Bundle();
args.putString(FragmentB.DATA_RECEIVE, data);
fragmentB .setArguments(args);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragmentB )
.commit();
}
}
FragmentB implementation is:
public class FragmentB extends Fragment{
final static String DATA_RECEIVE = "data_receive";
TextView showReceivedData;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_B, container, false);
showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
}
#Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
if (args != null) {
showReceivedData.setText(args.getString(DATA_RECEIVE));
}
}
https://developer.android.com/training/basics/fragments/communicating.html
This document has given information in detail, you can go through it.
In your situation, you can apply this way to communicate between two fragments.

Categories

Resources