FragmentTransaction adds content to the wrong LinearLayout - android

I have a search interface (with an android search widget). When I retrieve results, each results is wrapped into a folding-cell. Once the folding-cell is loaded, I fill the cell-title with a simple TextView. Then, I fill the content with a TextView (which works). In addition to the TextView, my cell-content also contains a LinearLayout. I use this layout to add a fragment, using a FragmentTransaction.
My problem is that each fragment is supposed to fill a different folding-cell, but only they all adds to the first folding-cell (so I guess that FragmentTransaction manager is adding all fragments to the same LinearLayout, the one of the first Folding-Cell).
Here is a screen of 1st and 2nd folding-cells, unfolded:
Here is the code for the search results :
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject row = jsonarr.getJSONObject(i);
Bundle args = new Bundle();
args.putString("email", row.getString("email"));
args.putString("name", row.getString("nom_organisme"));
Fragment newFragment = new FragmentOrganisationFoldingCell();
newFragment.setArguments(args);
getFragmentManager().beginTransaction().add(R.id.container_organisation_presentation_for_search, newFragment).commit();
organisationList.add(newFragment);
}
if(jsonarr.length() == 0){
errorText.setVisibility(View.VISIBLE);
}
} catch (JSONException e) {
e.printStackTrace();
}
Here is the FramgmentOrganisationFoldingCell:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_organisation_folding_cell, container, false);
final FoldingCell fc = (FoldingCell) view.findViewById(R.id.folding_cell);
Bundle args = getArguments();
TextView organisationName = view.findViewById(R.id.search_organisation_default_name);
organisationName.setText(args.getString("name"));
TextView t = view.findViewById(R.id.cell_content);
t.setText(args.getString("name"));
LinearLayout fragContainer = (LinearLayout) view.findViewById(R.id.cell_content_frag);
getFragmentManager().beginTransaction().replace(fragContainer.getId(), new FragmentProfileOrganisation(), "Organisation" + args.getString("name")).commit();
fc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fc.toggle(false);
}
});
return view;
}
Here is fragment_organisation_folding_cell, which is the view I inflate in FragmentOrganisationFoldingCell :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block">
<com.ramotion.foldingcell.FoldingCell
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/folding_cell"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false">
<!-- CONTENT (UNFOLDED) LAYOUT (MUST BE AT LEAST 2x times BIGGER than content layout bellow)-->
<include layout="#layout/cell_content_layout" />
<!-- TITLE (FOLDED) LAYOUT (MUST BE AT LEAST 2x times SMALLER than content layout above) -->
<include layout="#layout/cell_title_layout" />
</com.ramotion.foldingcell.FoldingCell>
</LinearLayout>
Here is the XML code for the cell_content_layout, which contains the LinearLayout I use to add my fragments. (So I beleive that this is the file that creates the trouble).
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="60sp"
android:layout_margin="40dp"
android:id="#+id/cell_content"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/cell_content_frag">
</LinearLayout>
</LinearLayout>
Here is the fragment_organisation_search XML file :
...
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/block"
android:id="#+id/container_organisation_presentation_for_search"
android:layout_margin="5dp">
</LinearLayout>
...
Do anyone have any trouble adding fragments into Folding-cells too? If anyone have any idea I would be really thankful !

The following command in your code that is parsing search results will add newFragment to a view with ID R.id.container_organisation_presentation_for_search. That ID is in your XML for the actual fragment.
getFragmentManager().beginTransaction().add(R.id.container_organisation_presentation_for_search, newFragment).commit();
I think instead what you want may be:
getFragmentManager().beginTransaction().add(R.id.cell_content_frag, newFragment).commit();

Related

How to fit a LinearLayout in a ScrollView?

Earlier on I asked a question about how to reach the last item of a scrollview and someone pointed out that I should be using NestedScrollView, at first it worked but now it's not what I want.
I want to fit my list of item in the ScrollView so only that part of the screen can be scrolled and the other parts stay at their place (the 3 TextView)
So basically my xml file is like this :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="#+id/cl_framgnent_detail_apero"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context=".ui.home.AperoDetailFragment">
<TextView
android:id="#+id/name_apero"
/>
<TextView
android:id="#+id/date_apero"
/>
<TextView
android:id="#+id/ingredient_title_apero"
/>
<ScrollView
android:id="#+id/rv_apero_ingredient"
android:layout_width="408dp"
android:layout_height="603dp"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/ingredient_title_apero"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ingredient_title_apero"
app:layout_constraintVertical_bias="1.0">
<LinearLayout
android:id="#+id/vertical_layout_ingredient"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
And in my Java code I try to populate my list with the following code :
public class AperoDetailFragment extends Fragment {
private View root;
private Apero detailApero;
public AperoDetailFragment(Apero apero) {
this.detailApero = apero;
}
#Override
public View onCreateView(#NonNull final LayoutInflater inflater,
final ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_detail_apero, container, false);
TextView name = (TextView) root.findViewById(R.id.name_apero);
name.setText(detailApero.getName());
TextView date = (TextView) root.findViewById(R.id.date_apero);
date.setText(detailApero.getDate());
LinearLayout ll = (LinearLayout) root.findViewById(R.id.vertical_layout_ingredient);
LinearLayout a = new LinearLayout(root.getContext());
ConstraintLayout.LayoutParams lparams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT);
a.setLayoutParams(lparams);
a.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < 20; i++) {
Button b = new Button(root.getContext());
b.setText("Button " + i);
a.addView(b);
}
ll.addView(a);
return root;
}
}
The problem is that the item are covering the whole screen instead of staying in the parent container (ScrollView) :
How can I fit my list of item to stay in the parent ?
If this is your actual code, then it might help to set constraints to the text views too.
Also, if your ScrollView has a fixed height, then you should remove either the top or bottom constraint. So if you want it to stick to the bottom, remove the top constraint.
I solved this with removing the ScrollView and using a ListView

Displaying internal intent within a fragmentnot working

I have a code to call the intent to display the running services screen. But i wanted it to be displayed within a fragment. But am not able to do that. I call this intent from the java class "bottompage.java" which is the fragment for bottom half of the page. But still when the button is clicked this intent occupies the full screen.
Activity main:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_display);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer1, new TopPage());
fragmentTransaction.add(R.id.fragmentContainer2, new BottomPage());
fragmentTransaction.commit();
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
Bottompage.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View secondview = inflater.inflate(R.layout.bottom_fragment,container,false);
Button dummy = (Button) secondview.findViewById(R.id.dummy);
dummy.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
final String APP_DETAILS_PACKAGE_NAME ="com.android.settings";
// Here you need to define the package name
final String SCREEN_CLASS_NAME ="com.android.settings.RunningServices";
Intent servicesintent = new Intent();
servicesintent.setAction(Intent.ACTION_VIEW);
//intent.setAction(Intent.ACTION_VIEW);
servicesintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
servicesintent.setClassName(APP_DETAILS_PACKAGE_NAME, SCREEN_CLASS_NAME);
BottomPage.this.getActivity().startActivity(servicesintent);
}
});
return secondview;
}
Main.xml
The xml file for 2 fragments
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<TextView
android:layout_width="157dp"
android:layout_height="wrap_content"
android:text="Second page"
android:id="#+id/tv2"
android:layout_gravity="center_horizontal"
android:layout_weight="0.06" />
<FrameLayout
android:id ="#+id/fragmentContainer1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:layout_weight="0.06"></FrameLayout>
<FrameLayout
android:id ="#+id/fragmentContainer2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_below="#+id/fragmentContainer1"></FrameLayout>
The xml file for the bottom fragment
BottomPage.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/bottom_fragment">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="call services"
android:id="#+id/dummy"
android:layout_gravity="center_horizontal" />
How do i make the intent "servicesintent" in bottompage.java to display the running services within the fragment "fragmentcontainer2". Currently its taking full screen.
I am not shure what you exactly want
I use this code to display the Intent that activated my Fragment in the Log.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
Activity parent = this.getActivity();
Intent intent = (parent == null) ? null : parent.getIntent();
if (intent != null) {
Log.d(Global.LOG_CONTEXT, "onCreateView " +
intent.toUri(Intent.URI_INTENT_SCHEME));
}
Instead of adding it to the Log you can set the value to a textview.
How do i make the intent "servicesintent" in bottompage.java to display the running services within the fragment "fragmentcontainer2".
You don't. You cannot embed third-party UIs inside your own, except in very specific circumstances (e.g., app widgets and a home screen).
Also note that there is no requirement that any device have a com.android.settings.RunningServices activity in com.android.settings that is exported.

How to replace an Android fragment with another fragment inside a ViewPager?

I have a view pager consisting of 4 tabs. Each tab holds its own fragment.
How would I be able to use fragment transaction to replace the fragment in tab 3 with a new fragment?
I've tried a lot of things, but I have not been able to come up with a solution at all. I've tried looking around on google and stackoverflow, but with no success.
I assume that your fragment has a button that is put in the center. By clicking on it, you can change the layout stays under of this button. The content/layout of the first fragment you mentioned should be replaced with wrapperA and the content/layout of the second one should be replaced with wrapperB. I put a simple red background for wrapperA to distinguish it with wrapperB, wrapperB is also green due to the same reason. I hope this is what you want:
public class SwitchingFragment extends Fragment {
Button switchFragsButton;
RelativeLayout wrapperA, wrapperB;
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layout_switch, container, false);
wrapperA = (RelativeLayout) rootView.findViewById(R.id.wrapperA);
wrapperB = (RelativeLayout) rootView.findViewById(R.id.wrapperB);
switchFragsButton = (Button) rootView.findViewById(R.id.switchFragsButton);
switchFragsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (wrapperB.getVisibility() == View.GONE) {
wrapperB.setVisibility(View.VISIBLE);
// There is no need to change visibility of wrapperA since it stays behind when wrapperB is visible.
// wrapperA.setVisibility(View.GONE);
}
else {
wrapperB.setVisibility(View.GONE);
// Again, there is no need.
// wrapperA.setVisibility(View.VISIBLE);
}
}
});
return rootView;
}
}
The layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<!-- The content of first fragment should be in "wrapperA". -->
<RelativeLayout
android:id="#+id/wrapperA"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/red"
android:visibility="visible">
</RelativeLayout>
<!-- The content of second fragment should be in "wrapperB". -->
<RelativeLayout
android:id="#+id/wrapperB"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/green"
android:visibility="gone">
</RelativeLayout>
<!-- As I said, I assume that the layout switcher button is stable
and so it should be in front of the switching layouts. -->
<Button
android:id="#+id/switchFragsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#color/black"
android:text="Switch"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="#color/white"/>
</RelativeLayout>
Alternatively, you can try to change the fragment directly by notifying your FragmentPagerAdapter as described in this link:
Replace fragment with another fragment inside ViewPager

Android adding Fragment inside Fragment

Hi there (and thanks in advance),
I have an application with a Google Play Store-like layout (using PagerTabStrip with 5 sub fragments). In some of those fragments I will need to display a little info regarding the last time the data was updated.
I immediately thought of creating a fragment (LastUpdatedFragment) which I would then add (nest) to the fragments I needed. At first, and since the last updated date was supposed to be the same for every screen, things were working (I simply added the fragment in the xml of the parent Fragments I needed and inside onCreateView I would put the date in the TextView), but after some changes I now need to send a specific date for each one of these LastUpdatedFragment instances.
I came up with one way - creating new custom attributes for my Fragment and then I would set the date I wanted. After some reading I stumbled across a easier way (Fragments within Fragments - dinamically adding the fragment using FragmentManager) - I simply needed the parent Fragment to handle the input parameters and pass it to the child fragment.
The problem is that, although I get no errors I also get no child fragment, it just does not display. I would be grateful if you could guide me in the right direction.
ScoreBoardFragment.java -> Parent Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_scoreboard, container,
false);
for (int i = 0; i < tvCount; i++) {
tvName = "f_scoreboard_header_tv" + String.valueOf(i);
resID = getResources().getIdentifier(tvName, "id",
_activity.getPackageName());
header = (TextView) rootView.findViewById(resID);
header.setTypeface(MyGlobalConfig.getInstance().getHeadersFont());
}
FragmentManager childFragMan = getChildFragmentManager();
FragmentTransaction childFragTrans = childFragMan.beginTransaction();
LastUpdatedFragment fragB = new LastUpdatedFragment();
childFragTrans.add(R.id.FRAGMENT_PLACEHOLDER, fragB);
childFragTrans.addToBackStack("B");
childFragTrans.commit();
return rootView;
}
fragment_scoreboard.xml (simplified but displaying everything else)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/FRAGMENT_PLACEHOLDER"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
style="#style/ListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/f_scoreboard_header_tv0"
style="#style/ListViewRowHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#" />
</LinearLayout>
<ListView
android:id="#+id/f_scoreboard_lvbody"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true" >
</ListView>
</LinearLayout>
LastUpdatedFragment.java -> Child Fragment
public class LastUpdatedFragment extends Fragment{
private View rootView;
private TextView tv;
private Context ctx;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(
getActivity()));
this.ctx = getActivity().getApplicationContext();
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_date, container,
false);
tv = (TextView) rootView.findViewById(R.id.f_date_tv);
tv.setTypeface(MyGlobalConfig.getInstance().getBodyFont());
tv.setText(getString(R.string.lastupdated) + ": " + Util.getLastUpdated(ctx));
return rootView;
}
}
fragment_date.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/f_date_tv"
style="#style/LastUpdatedTV"
android:layout_width="match_parent"
android:text="Data de última actualização: 27/12/2014 21:30" />
</LinearLayout>
Try to use FrameLayout instead of LinearLayout as Placeholder.

match_parent not working xml android

I'm trying to make buttons wich would change part of the context, but the match_parent not working propertly.
got java main file:
class public MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setIcon(R.drawable.ic_launcher);
Button bn1 = (Button) findViewById(R.id.navbar_1);
Button bn2 = (Button) findViewById(R.id.navbar_2);
bn1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentMeters fr = new FragmentMeters();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.layout_to_replace, fr);
ft.commit();
}
});
bn2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentValues fr = new FragmentValues();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.layout_to_replace, fr);
ft.commit();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
Then another java class FragmentMeters (and similar FragmentValues):
public class FragmentMeters extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_meters, null);
return view;
}
}
And main XML, something like this:
<LinearLayout
android:id="#+id/navbar"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="82dp"
android:background="#color/highlighted_text_material_dark"
android:weightSum="4">
<Button
android:id="#+id/navbar_1"
android:text="#string/navbar_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="13sp"
android:background="#android:color/transparent"
android:gravity="bottom|center_horizontal" />
<Button
android:id="#+id/navbar_2"
android:text="#string/navbar_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="13sp"
android:background="#android:color/transparent"
android:gravity="bottom|center_horizontal" />
</LinearLayout>
<LinearLayout
android:id="#+id/layout_to_replace"
android:orientation="horizontal"
android:layout_below="#+id/navbar"
android:layout_width="match_parent"
android:background="#color/dim_foreground_disabled_material_dark"
android:layout_height="82dp"
android:weightSum="4"/>
And I'm trying to replace the LinearLayout (id="layout_to_replace") with this fragment_meters.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_below="#+id/navbar"
android:layout_width="match_parent"
android:layout_height="82dp"
android:background="#color/dim_foreground_disabled_material_dark"
android:weightSum="4">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="METERS"/>
</LinearLayout>
But I'm getting this:
Instead of matching it parent's width/height.
i know this issue,in some cases when inflating a layout the arguments layout_width and layout_height change to wrap content.
i suggest to you to set layout params manually after inflating:
View view = inflater.inflate(R.layout.fragment_meters, null);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
(for height put what u want)
Deleting android:weightSum="4" from the LinearLayout with the id #+id/layout_to_replace should solve your problem.
You should also consider adding the gravity attribute on the corresponding TextView.
the best way to it is add resource file in values folder that called dimens.xml, and add there a dimen, like this:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<dimen name="width">100dp</dimen>
<dimen name="height">100dp</dimen>
</resources>
and in the java code you should get those values from resources by context, like this:
int width = getApplicationContext().getResources().getDimension(R.dimen.width);
int height = getApplicationContext().getResources().getDimension(R.dimen.height);
#tomáš-john, the issue is exactly like #liran-peretz assumed: your view from fragment_meters does not have "match_parent" in runtime. But the solution should be different.
The reason for this is because you passing null as "view root" when you inflate this view in the FragmentMeters! When no "view root" is passed at inflation - then layout params of "root element" from fragment_meters xml is ignored and thus this is not "match_parent" in LinearLayout.
Instead you have to do:
inflater.inflate(R.layout.fragment_meters, parent)
or with attachToRoot set to false (when you don't want your view to be added to the parent).
inflater.inflate(R.layout.fragment_meters, parent, false);
Some more links from the following answer could be helpful as well:
https://stackoverflow.com/a/25528527/3134602

Categories

Resources