I have this problem - I guess someone can surely put light on what the heck is going wrong here...
My overall flow goes like this - Activity(#+id/activity) shows a fragment(#+id/image_container) from screen bottom when a button is tapped(keyboard closes if present and fragment shown sliding upwards from bottom), this fragment shows a viewpager with page indicator in linear layout, viewpager shows another fragment which contains recycler view with horizontal gridlayoutmanager. This recycler view contains various imageview and i need to arrange them keeping my rows fixed say 3 but columns can be variable based on screen width and density. Imageview has fixed height and width.
This is my activity 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:id="#+id/activity">
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentTop="true" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="4dp"
android:id="#+id/divider"
android:layout_below="#+id/toolbar"/>
<include
layout="#layout/edit_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="#+id/divider"/>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/edit_bar" />
<FrameLayout
android:id="#+id/image_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/container"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
// Fragment inside the image_container
<?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="vertical"
android:weightSum="1">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="12dp"
android:layout_weight=".9"/>
<LinearLayout
android:id="#+id/sliderDots"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center_vertical|center_horizontal"
android:orientation="horizontal"
android:layout_weight=".1"/>
// Fragment inside viewpager
<?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.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="26dp"
android:paddingRight="26dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
// Item inside recycler view
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/imageView"
android:layout_width="48dp"
android:layout_height="48dp"
tools:visibility="visible"
android:layout_margin="6dp"/>
// Fragment code which gets added to image_container upon button tap
FragmentManager fm = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.view_transition_up_from_bottom, R.anim.view_transition_down_to_bottom);
fragmentTransaction.add(R.id.image_container, new ImageFragment(activity.getApplicationContext())).commit();
Inside this ImageFragment i calculate the rows(this is fixed let's say 3) and columns(Math.round((dpWidth - 52) / 60)) - 52(26*2 - for both side of recycler view, 60 - space occupied my 1 item including width and margin(L+R)), hence i know the images to be shown in each page and pass it to ImageViewFragment containing the recycler view which is used by adapter.
I use
recyclerView.setLayoutManager(new CustomGridLayoutManager(getActivity(), 3, CustomGridLayoutManager.HORIZONTAL, false));
to make my recycler view and hence i use fixed rows.
So my question is -
1. I wrote the code to keep my rows fixed and calculate columns based on screen width but sometimes i see too much spacing from right side of recycler view to screen edge, i kept it fixed with 26 dp but it shows more that that. How can i implement this type of functionality where i see uniform spacing in grid form??
2. How to handle orientation change when grid fragment is open, my activity is not redrawn. as i see i can only override onConfigurationChanged.
Related
My app adds fragments with values to the main activity at runtime but I need to be able to change the screen orientation without losing those values. The main issue is my adding of android:configChanges="orientation|screenSize" to the manifest works, but a large amount of extra space is added to the top of the app, so at either orientation after the first change, about a fourth of the screen is inaccessible white space.
activity_main.xml
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:fitsSystemWindows="true"
android:theme="#style/MyAppTheme">
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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"
android:layout_marginTop="25dp"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:layout_marginTop="8dp">
<TextView
android:id="#+id/manu_label"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:text="Manufacturer:"
android:textSize="12sp"
android:gravity="center"
android:layout_marginBottom="4dp"
android:layout_marginLeft="8dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<Spinner
android:id="#+id/manu_spinner"
android:theme="#style/SpinnerStyle"
android:layout_width="80dp"
android:layout_height="20dp"
android:dropDownWidth="150dp"
android:layout_marginLeft="8dp"
android:background="#drawable/cell_background"
android:layout_toRightOf="#id/manu_label"
android:layout_alignParentTop="true">
</Spinner>
<LinearLayout
android:id="#+id/panels_container"
android:orientation="vertical"
android:layout_below="#id/manu_spinner"
android:layout_alignParentLeft="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
My java code does not manipulate the view except to add fragments to a linear layout:
private View.OnClickListener cableListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft = manager.beginTransaction();
PanelsFragment frag = PanelsFragment.newInstance();
cables.add(frag);
ft.add(R.id.panels_container, frag, Integer.toString(trans.indexOf(frag)));
ft.commit();
}
};
Is there a way to prevent the extra space between my app bar and the scrollview, or do I need a different strategy? I did try overriding the onSaveInstanceState and onRestoreInstanceState, but my methods supposedly required a higher API than my minimum of 14. Any suggestions would be appreciated.
EDIT: Due to the nature of the project, I cannot provide a picture of the issue. When the app first starts, there is almost no space between the label and spinner with "manu" id's and the app bar. However, when the screen goes from portrait to landscape, at least 60dp of inaccessible space is between the app bar and the label and spinner. I noted that the 25dp of top margin for the content view was needed otherwise its contents started behind the app bar.
My problem was unexpectedly solved by specifying the height, width and margins for the content view in activity_main.xml:
<include
layout="#layout/content_main"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginTop="0dp" />
I'm working on an android app and am using a toolbar at the top of the screen and a navigation bar at the bottom of the screen. I'm using a single activity to create the top and bottom toolbars and fragments to change the content between the toolbars. However, when the contents in the fragment go beyond the size of the screen, the bottom bar disappears.
Here is my home activity xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_home"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.rentables.testcenter.HomeActivity">
<include
android:id="#+id/toolbar_main"
layout="#layout/toolbar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<fragment android:name="com.rentables.testcenter.HomeFragment"
android:id="#+id/fragment_place"
android:layout_weight="0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="#layout/fragment_home" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="bottom">
<include
android:id="#+id/toolbar_navigate"
layout="#layout/toolbar_navigate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"/>
</LinearLayout>
</LinearLayout>
Im guessing it's because of the inner linear layout I have, but I wasn't sure how else to get the nav bar to stay static at the bottom. Any help would be awesome. Thanks
Figured it out. I just changed the whole thing to a relative layout, got rid of the inner linear layout, and instead of gravity I used alignParentBottom="true".
I have a little strange problem for me. I need to translate view which is located over a viewpager on recyclerview scroll. RecyclerView is located in fragment and fragments are located in viewpager. When I scroll recyclerview in fragment and want to translate View which is located over viewpager my problem occurs. ViewPager is moving up to fill space left by translated view, but fragments aren't. Because of it I can see space empty space on viewpager. I checked it by setting viewpager background and i saw that viewpager actually resized to match container but fragments remained still. Any ideas how to force it to works as it should be? This code works perfectly when recyclerview and view which I want to resize are on same fragment.
Issue look like this http://i.imgur.com/wyxXGYh.png
Layout look like this
ViewPagerFragment
<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"
android:orientation="vertical"
android:clipToPadding="false">
<android.support.v7.widget.RecyclerView
android:id="#+id/subcategory_fragment_recycle_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
Layout with Viewpager
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/fragment_category_sliding_tab_layout">
<android.support.v4.view.ViewPager
android:id="#+id/fragment_category_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="100dp"
android:clipToPadding="false"
android:background="#0000FF"
android:animateLayoutChanges="true">
</android.support.v4.view.ViewPager>
<TextView
android:id="#+id/scrollTemp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FF0000"
android:gravity="center|center_vertical"
android:text="TEMP"
android:textSize="40dp" />
</FrameLayout>
For detecting scrollevents and triggering show/hide of temp view I am using basically this HidingScrollListener https://mzgreen.github.io/2015/02/28/How-to-hideshow-Toolbar-when-list-is-scrolling%28part2%29/. As I said it works perfectly when recyclerview and view which I want to scroll are on same fragment.
In my app, I want to keep a same Ad banner at the bottom of all the screens, so I use one Activity with multiple fragments.
In the Activity's layoutfile(activity_mail.xml), I have a FrameLayout as the container of the fragments and a AdView at the bottom to show the banner Ads from Admob.
<RelativeLayout
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=".MainActivity"
tools:ignore="MergeRootFrame">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<fragment
android:id="#+id/adFragment"
android:name="com.jiyuzhai.wangxizhishufazidian.MainActivity$AdFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Layout of the fragment to replace the existing fragment
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#drawable/theme_color"
android:layout_alignParentTop="true"
android:text="Topbar in fragment"
android:textColor="#android:color/white"
android:textSize="30sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#drawable/theme_color"
android:layout_alignParentBottom="true"
android:text="Bottombar in fragment"
android:textColor="#android:color/white"
android:textSize="30sp"/>
</RelativeLayout>
Code to replace the existing fragment
fragment = new LinmoFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out);
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.commit();
But when I replace the fragments in the container, the bottom area of the fragment was hide by the AdView, in other words, the fragment was out of the Framelayout, I want the fragment totally inside the container. is that possible?
The following is what I want
and this is what I get(The Ad banner hide the bottombar of the fragment)
Any idea?
By the way, I find there is no way to keep a same banner for all screens with multiple Activities in Android, many people on SO said you need to use Single Activities with multiple fragments, then you can add/remove your fragments dynamically without reload new banner, but, there is no code found for this approach, so I try it myself. if you have better solutions, please help me.
Try this:
<RelativeLayout
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=".MainActivity"
tools:ignore="MergeRootFrame">
<fragment
android:id="#+id/adFragment"
android:name="com.jiyuzhai.wangxizhishufazidian.MainActivity$AdFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/adFragment" />
</RelativeLayout>
The changes I made to your original layout file were moving the adFragment definition above the frame layout, made the frame layout height wrap content, and added the layout_above attribute to make the frame layout appear above the ad fragment.
An alternative approach would have been to use a vertical linear layout with the frame layout first with a layout weight of 1 (and the ad fragment would not have a layout weight).
By the way, the fragment is contained completely within your frame layout. The frame layout was just being overlapped by the ad fragment in your original layout. The above suggestion makes it so that there is no overlap.
Hope this helps.
If you want to both avoid overlapping and make the container fill the screen then you should just change RelativeLayout to LinearLayout.
<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"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame"
android:orientation:"vertical"
>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<fragment
android:id="#+id/adFragment"
android:name="com.jiyuzhai.wangxizhishufazidian.MainActivity$AdFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
I'm having an issue where my Fragment view inside a LinearLayout isn't streching to the parent's height and width. But it is a little bit more complicated since I have two Fragments inside that Fragment.
Here's the Activity's view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center|fill"
android:orientation="vertical"
android:padding="8dp" >
</LinearLayout>
Here's the parent fragment XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:background="#FF00FF"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/mtg_player1_fragment_wrapper"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#0000FF"
android:orientation="horizontal" >
</LinearLayout>
<LinearLayout
android:id="#+id/mtg_player2_fragment_wrapper"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF0000"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
And the child (player) fragment XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mtg_player_life_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/mtg_player_life_count"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:gravity="center_vertical|center_horizontal"
android:text="0"
android:textSize="140sp" />
</LinearLayout>
I'm adding the parent fragment like this (via clicking on a list item):
getSupportFragmentManager().beginTransaction().replace(R.id.main_content, fragment, newFragmentClass.getSimpleName()).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
And the children fragment like this (on the parent's onViewCreated()):
mPlayer1Frag = (PlayerFragment) getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.player1_fragment_wrapper);
if (mPlayer1Frag == null) {
mPlayer1Frag = new PlayerFragment();
}
if (!mPlayer1Frag.isVisible()) {
((RoboSherlockFragmentActivity)getSherlockActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.player1_fragment_wrapper, mPlayer1Frag).commit();
}
mPlayer2Frag = (PlayerFragment) getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.player2_fragment_wrapper);
if (mPlayer2Frag == null) {
mPlayer2Frag = new PlayerFragment();
}
if (!mPlayer2Frag.isVisible()) {
((RoboSherlockFragmentActivity)getSherlockActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.player2_fragment_wrapper, mPlayer2Frag).commit();
}
What I get is the following:
What basically happened is:
The parent Fragment view didn't stretch vertically to fill the entire activity's view (no pink appeared);
The TextView (green) didn't stretch to cover the children fragment layout (red/blue);
What I want to happen is for the parent UI to stretch in the entire activity, for the children to cover the entire parent and for the TextViews to cover the entire child. I could change it to use a single fragment (and may well do that), but I'd prefer if I could keep it this way, since it feels more organized :)
So, the question is, what am I doing wrong? Can't this be done using two fragments inside another?
In the onCreateView() method of a Fragment always inflate the layout file using the container parameter of that method like this:
inflater.inflate(R.layout.parent_view, container, false);
This way the inflated view will be given proper LayoutParams and it will behave as designed.