I have a viewpager (with actionbar sherlock) containing 4 SherlockFragment, all inside a SherlockFragmentActivity.
Each tab has it's own backStack (i can stack several fragments ON each SherlockFragment)
What i'm trying to do is when i select an item in the list, i want to make visible a ViewStub (which is a player)
My problem is that the ViewPager Does not redim itself. The player become visible but behind the viewpager.
Here is the main SherlockFragmentActivity :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="#style/ActivityDark"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
tools:context=".ActivityMain" >
<ViewStub
android:id="#+id/main_stubplayer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:inflatedId="#+id/fragment_allzic_player"
android:layout="#layout/view_player" />
<android.support.v4.view.ViewPager
android:id="#+id/main_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/main_stubplayer" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
Here is the ViewStub :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/banner_player_layout"
android:layout_width="match_parent"
android:layout_height="#dimen/cell_height"
android:background="#color/clr_player"
android:clickable="true" >
[...the content does not matter the height is fixe]
</RelativeLayout>
Here is how i make is visible :
public void showPlayerBanner(String title) {
if (mViewPlayer == null) {
ViewStub stub = (ViewStub) findViewById(R.id.main_stubplayer);
mViewPlayer = stub.inflate();
} else {
mViewPlayer.setVisibility(View.VISIBLE);
}
}
Try LinearLayout vertical instead of RelativeLayout and set the min/max height to the viewstub.
To know more about the layout differences, the article is here
Related
In an Android project, I have an Activity that contains (from top to bottom) a header, a RecyclerView and a RelativeLayout.
Code sample :
<android.support.design.widget.CoordinatorLayout ...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
...
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
This is the behaviour I want : the RelativeLayout is "folded" by default, i.e. under the RecyclerView. When the user swipes up, the RelativeLayout expands to use the whole screen, and folded again when swipes down.
What is the right way to do it ? As I want the RelativeLayout to be BELOW the RecyclerView when folded, and OVER it when expanded. I tried setting the dependencies between elements dynamically but couldn't manage to do so.
Thanks for any help or advice on how to organize the activity to get such a behaviour.
EDIT
This is the XML structure :
<CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</AppBarLayout>
<RecyclerView
android:id="#+id/top_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/app_bar"
android:layout_above="#+id/relativelayout_footer" />
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentBottom="true">
<TextView ...>
<RecyclerView
android:id="#+id/included_list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
</CoordinatorLayout>
And the listener :
top_list.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
app_bar.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
included_list.setVisibility(playlistOpened ? View.GONE : View.VISIBLE);
Transition cb = new ChangeBounds();
cb.setDuration(1000);
TransitionManager.beginDelayedTransition(slider, cb);
playlistOpened = ! playlistOpened;
As you see, I switch the visibility of the elements in order to reorganise the view. When the included_list is set to VISIBLE, it pushes up the TextView.
The only problem is that the top_list and the app_bar disappear before being covered by the RelativeLayout. I tried adding a Listener to the Transition and do these when the transition ends, but it doesn't work (I guess because they're not set to GONE at the beginning, so the RelativeLayout can't move up). Any idea of how to do so ? Maybe I should open another question for it ?
Okay, a final attempt. I am back to RelativeLayout and added another one around the RecyclerView to fix its scrolling problem. However, transitions get tricky (and the listener complicated) then. In order to prevent the RecyclerView from popping away before the RelativeLayout with the TextView inside fully covers the latter, I had to include a fading transition to the RecyclerView, too. Hope this suits you.
XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rlwithrecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/rlwithtextview"
android:layout_alignParentTop="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlwithtextview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="#+id/textview"
android:text="Just a test" />
</RelativeLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
onClick():
#Override
public void onClick(View v) {
RelativeLayout rlWithRecyclerView = findViewById(R.id.rlwithrecyclerview);
RelativeLayout.LayoutParams layoutParamsRlWithRecyclerView;
RelativeLayout rlWithTextView = findViewById(R.id.rlwithtextview);
RelativeLayout.LayoutParams layoutParamsRlWithTextView;
if (rlWithTextView.getLayoutParams().height == MATCH_PARENT) {
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ABOVE, R.id.rlwithtextview);
} else {
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, 0);
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
}
layoutParamsRlWithTextView.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Transition changeBounds = new AutoTransition();
changeBounds.setDuration(500);
TransitionManager.beginDelayedTransition(rlWithRecyclerView, changeBounds);
TransitionManager.beginDelayedTransition(rlWithTextView, changeBounds);
rlWithRecyclerView.setLayoutParams(layoutParamsRlWithRecyclerView);
rlWithTextView.setLayoutParams(layoutParamsRlWithTextView);
}
Although I got credit for the two other answers, I will eventually delete them, since they don't solve the problem.
i'm using a Material swipe tab to show with swipe 3 different fragment layout.
This is the xml layout for swipe tab:
<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:orientation="vertical"
tools:context=".MainActivity">
<include
android:id="#+id/tool_bar"
layout="#layout/tool_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<com.android4devs.slidingtab.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
></android.support.v4.view.ViewPager>
</LinearLayout>
Now the xml layout fragment of swipe have a button fixed into bottom of layout so when i swipe to this fragment the layout of fragment is cut see image:
there some way to fix the layout fragment into ViewPager or a way for scroll it with a scroller view?
Thanks
In your second Fragment, you can use
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.fullScroll(View.FOCUS_DOWN);
}
});
To scroll your ScrollView to the bottom, so your Button will be totally visible.
Following XML is a test layout for my view. It shows a NavigationDrawer on the left side with a toolbar on top of the view. The toolbar shows a title and a hamburger-Icon on the top left to toggle the NavigationDrawer. Everything works fine:
My XML (I removed all height/width attributes because it's better readable):
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:fitsSystemWindows="true">
<LinearLayout
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<!-- ** MY VIEW ELEMENTS **-->
</LinearLayout>
<LinearLayout
android:id="#+id/drawer_leftpane"
android:orientation="vertical"
android:layout_gravity="left|start"
android:background="#FFFFFF"
android:fitsSystemWindows="true">
<TextView
android:text="Test string on top of list" />
<android.support.v7.widget.RecyclerView
android:id="#+id/drawer_menulist"
android:scrollbars="vertical"
android:choiceMode="singleChoice"
android:divider="#null" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
In the section <!-- ** MY VIEW ELEMENTS **--> I insert the view Elements for the different views (that's the only thing who changes between all views).
I have many views which need this layout above. I know about includes, merges and compound views and read many articles about these. But I am not able to create a layout for this special case and I would like to avoid copy paste the whole layout throughout all my views.
In the end I want something like this for all my views:
<?xml version="1.0" encoding="utf-8"?>
<MyDrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_layout"
android:fitsSystemWindows="true">
<!-- ** MY VIEW ELEMENTS **-->
</MyDrawerLayout>
Is that even possible? Or is there another way to achive this? Thanks in advance
Well, I would just use LayoutInflater.
First of all I would create FrameLayout as a container for my layouts.
Then I would inflate required layout.
And if I would need to inflate another layout, I would just do view_container.removeAllViews( ) and inflate that another layout.
Everything in action
main.xml
<!-- it's not full layout, I've just taken a fragment from your example -->
<LinearLayout
android:orientation="vertical" >
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<!-- This is where you hold required layout -->
<FrameLayout
android:id="#+id/view_container"
android:layout_width = "match_parent"
android:layout_height = "match_parent" />
</LinearLayout>
Main.java
public class Main extends AppCompatActivity
{
#Override public void onCreate( Bundle savedInstaceBundle )
{
super.onCreate( );
setContentView( R.layout.main );
FrameLayout view_container = ( FrameLayout ) findViewById( R.id.view_container );
/** To inflate layout **/
LayoutInflater inflater = getApplicationContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
inflater.inflate( /*R.layout.my_layout */, view_container );
/** To remove layout in 'view_container' **/
view_container.removeAllViews( );
/** To change layout in 'view_container' **/
// 1. Remove all views
// 2. Inflate required layout
}
}
P.S. I wrote it all in here, so I may have made some mistakes but the idea is still the same!
You need to remove this. This is the wrong idea:
<LinearLayout
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<!-- ** MY VIEW ELEMENTS **-->
</LinearLayout>
Just use this:
<android.support.v7.widget.Toolbar
android:id="#+id/my_awesome_toolbar"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
Find the View in Java, and then add views you inflate into it.
Then you can have separate XML layouts for the different Toolbar configurations you have and inflate them dynamically.
E.G.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
orientation:horizontal>
<TextView
android:id="#+id/action_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginRight="#dimen/dp_fortytwo"
android:text="#string/app_name"
android:textColor="#color/primary_text"
android:textSize="#dimen/dp_eighteen"/>
</LinearLayout>
It's convenient to keep a Singleton class for your navigation that has a reference to a ViewGroup in the Toolbar. You could inflate an "actionbar" into the Toolbar:
toolBar = (Toolbar) drawerLayout.findViewById(R.id.toolbar);
context.setSupportActionBar(toolBar);
actionBar = (ViewGroup) LayoutInflater.from(context()).inflate(R.layout.actionbar, toolBar, false);
toolBar.addView(actionBar);
Then add views as needed dynamically:
LayoutInflater.from(context).inflate(R.layout.actionbar_home_icon, actionBar, true);
I have a generic layout, to which I attach fragments:
<?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="match_parent"
android:background="#drawable/back"
android:orientation="vertical" >
<include
android:id = "#+id/login_header"
layout="#layout/header_layout"/>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
I have a fragment which I want to display on the right side of the screen.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="#dimen/two_third_width"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="#dimen/small_margin"
android:background="#drawable/stock_price_bg"
tools:context=".FoundItemFragment" >
</RelativeLayout>
The layout is displayed left-justified rather than right justified. When I color the fragment_container FrameLayout, I see that it takes the entire width of the screen. I attach the fragment with the following code in my "FoundItemFragment extends Fragment implements OnClickListener" class:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View fragView = null;
try {
fragView = inflater.inflate(layoutID, container, false);
//LoadData(fragView);
} catch (Exception ex) {
ex.printStackTrace();
}
return fragView;
}
The container parameter passed to this routine has the id of the fragment_container layout, so I am not attaching it to some other object which might have settings that override the alignParentRight setting. Why is the fragment displayed left-justified rather than right-justified?
The layout parent should be Relative Layout so that alignParentRight will work .
You are using the alignParentRight for a root element RelativeLayout
Just edit your container xml to
<?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:background="#drawable/back" >
<include
android:id = "#+id/login_header"
layout="#layout/header_layout"
android:layout_alignParentTop = "true"/>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:below = "#id/login_header"
android:layout_alignParentRight="true"/>
</LinearLayout>
<?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:background="#drawable/back"
android:orientation="vertical" >
<include
android:id = "#+id/login_header"
layout="#layout/header_layout"/>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
Since generic layout hold the container of the fragment, you should align/place the fragment there.
Placement of the views of the fragment should be done in fragment specific xml file
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.