I want to implement same kind of animation such as linked in does in android application for its Introduction(Login / register) screen.
I am using view pager for Introduction screen and i want to implement fadein fadeout animation on background image change, As per swipe right to left or vice versa.
I want to implement fadein and fadeout animation on background image change according to swipe of screen.
any help is appreciated.
Please take a look at my layout code
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/background_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="7" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:gravity="right"
android:orientation="horizontal" >
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginRight="5dp"
android:src="#drawable/icon_skip" />
<TextView
android:id="#+id/skip_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Skip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:gravity="bottom"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/logo" />
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context="com.xyz.View.IntroductionScreen" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="#+id/connection_bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:background="#drawable/button"
android:text="CONNEXION"
android:textColor="#android:color/white" />
<Button
android:id="#+id/register_bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="10dp"
android:background="#drawable/button"
android:text="INSCRIPTION"
android:textColor="#android:color/white" />
</LinearLayout>
</LinearLayout>
And View pager fragment layout is
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/text_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical" >
<TextView
android:id="#+id/tagline_tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:singleLine="true"
android:text="Laissez votre prochain job"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white" />
<TextView
android:id="#+id/details_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:maxLines="2"
android:text="vous trouver"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white" />
</LinearLayout>
</RelativeLayout>
sample Splashs creen this is what i want to implement.
Thank you
This is a lag free one and also handles the Buttons
Main Idea:
1) first create transparent background for your fragments.
2) Create LayerDrawable and add background image of each fragment as an item. Then add your LayerDrawable as a background of your viewpager.
3) in onCreate method set alpha of each layer correctly so just upper one has alpha value of 255.
4) set for each view of your FragmentStatPagerAdapter a tag that corresponds to drawable index that you declared in the LayerDrawable. for example when you open the app FragmentA is showing so its tag must correspond to upper drawable that is 2 (beginning from 0). last page tag must be 0 corresponds to lowest drawable.
5) change drawable of each view at the function transformPage
6) for adding the button use RelativeLayout.
In order to place buttons on top of all views use RelativeLayout. Later children are placing higher on the Z axis. You can see it in the code:
now lets see code:
MainActivity
public class MainActivity extends FragmentActivity {
ViewPager viewPager=null;
int numberOfViewPagerChildren = 3;
int lastIndexOfViewPagerChildren = numberOfViewPagerChildren - 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
final LayerDrawable background = (LayerDrawable) viewPager.getBackground();
background.getDrawable(0).setAlpha(0); // this is the lowest drawable
background.getDrawable(1).setAlpha(0);
background.getDrawable(2).setAlpha(255); // this is the upper one
viewPager.setPageTransformer(true, new ViewPager.PageTransformer() {
#Override
public void transformPage(View view, float position) {
int index = (Integer) view.getTag();
Drawable currentDrawableInLayerDrawable;
currentDrawableInLayerDrawable = background.getDrawable(index);
if(position <= -1 || position >= 1) {
currentDrawableInLayerDrawable.setAlpha(0);
} else if( position == 0 ) {
currentDrawableInLayerDrawable.setAlpha(255);
} else {
currentDrawableInLayerDrawable.setAlpha((int)(255 - Math.abs(position*255)));
}
}
});
}
class MyAdapter extends FragmentStatePagerAdapter
{
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment=null;
if(i==0)
{
fragment=new FragmentA();
}
if(i==1)
{
fragment=new FragmentB();
}
if(i==2)
{
fragment=new FragmentC();
}
return fragment;
}
#Override
public int getCount() {
return numberOfViewPagerChildren;
}
#Override
public boolean isViewFromObject(View view, Object object) {
if(object instanceof FragmentA){
view.setTag(2);
}
if(object instanceof FragmentB){
view.setTag(1);
}
if(object instanceof FragmentC){
view.setTag(0);
}
return super.isViewFromObject(view, object);
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/layerdrawable" >
</android.support.v4.view.ViewPager>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:layout_marginBottom="48dip" >
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sign in"
android:layout_margin="16dip"
android:background="#2ec6e4"
android:textColor="#FFFFFF" />
<Button
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Join us"
android:background="#2ec6e4"
android:layout_margin="16dip"
android:textColor="#FFFFFF"
/>
</LinearLayout>
</RelativeLayout>
LayerDrawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap
android:id="#+id/Idofbg3"
android:gravity="fill"
android:src="#drawable/bg3" />
</item>
<item>
<bitmap
android:id="#+id/Idofbg2"
android:gravity="fill"
android:src="#drawable/bg2" />
</item>
<item>
<bitmap
android:id="#+id/Idofbg1"
android:gravity="fill"
android:src="#drawable/bg1" />
</item>
</layer-list>
for lazy people who just do not want to declare fragments:
FragmentA
public class FragmentA extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a,container,false);
return v;
}
}
fragment_a.xml
<?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/FragmentA"
android:background="#android:color/transparent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="This is Fragment A"
android:textColor="#FFFFFF"
android:id="#+id/textView"
android:gravity="center"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Set a ViewPager.PageTransformer to the ViewPager and achieve the desired animation using aplha and translation animation properties.
The most important input is the position parameter passed to transformPage callback. The position value indicates how the view is positioned currently.
Assuming the views in ViewPager are full width, here is how position value need to be interpreted.
------------------------------------------------------------------------------------
position | what does it mean
------------------------------------------------------------------------------------
0 | view is positioned in the center and fully visible to the user.
-1 | view is positioned in the left and not visible to the user.
1 | view is positioned in the right and not visible to the user.
>-1 & <0 | view is being scrolled towards left and is partially visible.
>0 & <1 | view is being scrolled towards right and is partially visible.
------------------------------------------------------------------------------------
mPager.setPageTransformer(true, new ViewPager.PageTransformer() {
#Override
public void transformPage(View view, float position) {
// Ensures the views overlap each other.
view.setTranslationX(view.getWidth() * -position);
// Alpha property is based on the view position.
if(position <= -1.0F || position >= 1.0F) {
view.setAlpha(0.0F);
} else if( position == 0.0F ) {
view.setAlpha(1.0F);
} else { // position is between -1.0F & 0.0F OR 0.0F & 1.0F
view.setAlpha(1.0F - Math.abs(position));
}
// TextView transformation
view.findViewById(R.id.textView).setTranslationX(view.getWidth() * position);
}
});
Here is the layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_alignParentTop="true"
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView" />
</RelativeLayout>
Here is the screen record:
Related
I have a CoordinatorLayout with a custom view and a persistent bottom sheet. I have disabled hiding for the bottom sheet and want to show the top couple of views in a LinearLayout in the collapsed state. To account for different screen sizes, I dynamically set the peekHeight in my activity's onCreate, after everything has been laid out.
The issue is when the activity first starts, the BottomSheet peeks at one height, and then after it is expanded and collapsed again the peekHeight seems to have changed. Interestingly enough, it visually looks like the peekHeight added is the layouts activity padding (16dp). However, the BottomSheetBehavior reports the same peekHeight for both.
I have created a hacky workaround for this, but I want to see if there is anything I am doing wrong. Below is a gif showing when I do not have my workaround and one when I am using my workaround. I have also included the relevant code and layout files. Again, It seems to be directly related to my padding (16dp), but I don't understand how to fix it.
NOT using workaround:
Using workaround:
Activity:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_schedule_details_activity);
final CoordinatorLayout activityLayout =
(CoordinatorLayout) findViewById(R.id.edit_schedule_details_layout);
ButterKnife.bind(this);
// ... removed unrelated logic
final View bottomSheet = findViewById(R.id.edit_details_sheet);
final LinearLayout peekContainer = (LinearLayout) findViewById(R.id.info_title_container);
activityLayout
.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Set the measured peek height and add in 16 dps to account for inconsistency
// Adding the 16 dps is part of the workaround
bottomSheetBehavior.setPeekHeight(peekContainer.getHeight());
//+ (int) (16 * getResources().getDisplayMetrics().density)); /* workaround */
Timber.i("Title height: " + bottomSheetBehavior.getPeekHeight());
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(View bottomSheet, int newState) {
String stateString = "";
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
stateString = "Expanded";
/* workaround */
/*if(!bottomSheetSet){
// remove the extra 16 dp added since the layout now looks correct
bottomSheetBehavior
.setPeekHeight(
bottomSheetBehavior.getPeekHeight()
- (int) (16 * getResources().getDisplayMetrics().density));
bottomSheetSet = true;
}*/
}
else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
stateString = "Collapsed";
Timber.i("peekHeight = " + bottomSheetBehavior.getPeekHeight());
}
else if (newState == BottomSheetBehavior.STATE_HIDDEN) {
stateString = "Hidden";
}
else if(newState == BottomSheetBehavior.STATE_SETTLING) {
stateString = "Settling";
}
else if(newState == BottomSheetBehavior.STATE_DRAGGING){
stateString = "Dragging";
}
Timber.i("bottomSheetState = " + stateString);
}
#Override
public void onSlide(View bottomSheet, float slideOffset) {
}
});
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/edit_schedule_details_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_horizontal_margin"
android:background="#ff171e26">
<com.cel.cortetcommercial.widget.ring_view.RingView
android:id="#+id/edit_ringview"
android:layout_width="match_parent"
android:layout_height="400dip"
app:inner_radius="95dip"
app:outer_radius="130dip"
app:color="#color/colorSecondaryDark"
app:is_touchable="true"
app:text_size="12dip"
app:tick_length="0dip"
app:tick_width="0dip"
android:transitionName="#string/transition_details_to_edit"/>
<LinearLayout
android:id="#+id/add_remove_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
app:layout_anchor="#id/edit_ringview"
app:layout_anchorGravity="bottom">
<Button
android:id="#+id/remove_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"
android:layout_gravity="end"/>
<Button
android:id="#+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"/>
</LinearLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/edit_details_sheet"
android:layout_width="match_parent"
android:layout_height="250dp"
android:clipToPadding="true"
android:background="#color/colorPrimary"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
app:behavior_hideable="false">
<include layout="#layout/current_info_sheet">
</include>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
current_info_sheet:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/info_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/info_title_container">
<TextView
android:id="#+id/segment_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:text="#string/placeholder"
android:textAppearance="#android:style/TextAppearance.Material.Headline"
android:textColor="#color/white"/>
<TextView
android:id="#+id/time_remaining"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:text="#string/placeholder"
android:textColor="#color/white"/>
<Space
android:layout_width="1dp"
android:layout_height="16dp"/>
</LinearLayout>
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:textColor="#color/white"
android:text="#string/luminosity"/>
<SeekBar
android:id="#+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"/>
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"
android:textColor="#color/white"
android:text="#string/color_warmth"/>
<SeekBar
android:id="#+id/seekBar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_marginLeft="#dimen/activity_horizontal_margin"
android:layout_marginRight="#dimen/activity_horizontal_margin"/>
</LinearLayout>
I have a list with Swipe Actions on it using IOnTouchListener, as dragging occurs I am changing the Left of a LinearLayout to reveal a second LinearLayout behind it. That layout has two buttons, one is hidden. If the user does a "quick" swipe then I move the Left of the top view to a specific value and fire some code. This code changes the invisible button to be visible. When the ViewState of that button changes it makes the top view's Left snap back to 0 instead of staying where I place it. Any idea why it would do this or how to work around it.
The XML looks like... (But will change slightly based on the answer to another question I posted)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="fill_vertical"
android:background="#color/black"
android:id="#+id/Swipe"
>
<LinearLayout
android:id="#+id/LeftContentView"
android:layout_width="175dp"
android:layout_height="match_parent"
android:background="#color/yellow"
android:layout_alignParentLeft="true"
android:orientation="horizontal"
>
<Button
android:id="#+id/ApproveButton"
android:layout_width="0dp"
android:layout_weight=".72"
android:layout_height="match_parent"
android:background="#2796C3"
android:text="Approve"
android:layout_alignParentLeft="true"
/>
<Button
android:id="#+id/ApproveUndoButton"
android:layout_width="0dp"
android:layout_weight=".28"
android:layout_height="match_parent"
android:background="#215681"
android:text="Undo"
android:layout_toRightOf="#id/ApproveButton"
/>
</LinearLayout>
<LinearLayout
android:layout_alignParentRight="true"
android:id="#+id/RightContentView"
android:layout_width="175dp"
android:layout_height="match_parent"
android:background="#color/black"
android:orientation="horizontal"
>
<Button
android:id="#+id/DenyButton"
android:layout_width="0dp"
android:layout_weight=".72"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="Deny"
/>
<Button
android:id="#+id/DenyUndoButton"
android:layout_width="0dp"
android:layout_weight=".28"
android:layout_height="match_parent"
android:background="#860000"
android:text="Undo"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/TopContentView"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#1F1F1F">
<LinearLayout
android:layout_height="fill_parent"
android:layout_width="match_parent" >
<ImageView
android:id="#+id/UnreadImage"
android:layout_height="match_parent"
android:layout_width="7dp"
android:src="#drawable/vertical_blue_bar"
android:background="#2796C3"/>
<LinearLayout
android:id="#+id/ListText"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:padding="12dp">
<TextView
android:id="#+id/Text_Line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="13dip"
/>
<TextView
android:id="#+id/Text_Line2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="13dip"
/>
<TextView
android:id="#+id/Text_Line3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="11dip"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
I am not using Java, I am using Xamarin with C#. Here are the relevant pieces of code...
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
OriginalTouchX = Math.Ceiling(e.RawX);
index = e.ActionIndex;
pointerId = e.GetPointerId(index);
VelocityTracker.AddMovement(e);
break;
case case MotionEventActions.Move:
VelocityTracker.AddMovement(e);
ChangeX(newX);
VelocityTracker.ComputeCurrentVelocity(1);
float velocity = Math.Abs(VelocityTracker.GetXVelocity(pointerId));
if (velocity > SlowDrag && Math.Abs(distanceMoved) > (DragThreshold / 3))
{
QuickApprove();
}
break;
}
}
void QuickApprove()
{
ToggleUndoButton(true, true);
WaitingForUndo = true;
ChangeX(DragThreshold);
this.ApproveTimer.Start(true);
}
private void ToggleUndoButton(bool ShowUndo, bool LeftSide)
{
this.ApproveUndoButton.Visibility = ViewStates.Visible;
this.ApproveButton.Text = "Approving...";
}
private void ChangeX(int newX)
{
int width = this.TopContentView.Right - this.TopContentView.Left;
this.TopContentView.Left = newX;
this.TopContentView.Right = this.TopContentView.Left + width;
}
If in the ToggleUndoButton method I comment out the line
this.ApproveUndoButton.Visibility = ViewStates.Visible;
Everything works fine. The Left of TopContentView changes to be equal to my DragThreshold, the text changes to Approving... the timer starts, It stays this way for 2 seconds, then the code in my timer tick fires and the TopContentView is moved back to a Left of 0. If I leave in the visibility change then the TopContentView is immediately moved back to 0 instead of waiting until the timer is done.
I have a question regarding crossfading on a viewpager where I have objects that depends on their z-layer. I found this topic OnPageChangeListener alpha crossfading which provides the exact solution that I'm after except that the z-layers are ignored in the swiping, but only for the items on the left side, not the items on the right side.
First you can see the content on the left side, where the button is "cut" in half, next the transition, and, third, the item on the right side where the button is shown in its entirety. What I don't understand is why the button is only partly visible and what I need to do to make it fully visible?
content_main.xml:
<?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="#color/sand">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="30dp"
android:text="Hello World!" />
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_below="#+id/title" />
</RelativeLayout>
content_main_item.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="350dp">
<ImageView
android:id="#+id/background_color"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="center" />
<RelativeLayout
android:id="#+id/background_part"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/sand"
android:layout_gravity="center_horizontal|bottom">
</RelativeLayout>
<RelativeLayout
android:id="#+id/item_container"
android:layout_width="match_parent"
android:layout_height="350dp">
<ImageView
android:id="#+id/page_image"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:src="#drawable/smaller" />
<TextView
android:id="#+id/page_header"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignBottom="#+id/page_image"
android:layout_marginBottom="45dp"
android:text="Header Blue"
android:lines="2"
android:textColor="#android:color/black"
android:textAllCaps="true"
android:textStyle="bold"
android:gravity="center"
android:textSize="20dp" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
>
<Button
android:id="#+id/page_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="Click me"
/>
</FrameLayout>
</RelativeLayout>
</FrameLayout>
My modified CustomPageTransformer:
public class CustomPageTransformer implements ViewPager.PageTransformer {
public static final float ALPHA_VALUE = 0.8f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
View backgroundImageView = view.findViewById(R.id.background_color);
View contentView1 = view.findViewById(R.id.item_container);
if (position < -1) {
// This page is way off-screen to the left
} else if (position <= 0) { // [-1,0]
// This page is moving out to the left
if (backgroundImageView != null) {
// Fade the image in
backgroundImageView.setAlpha(ALPHA_VALUE + position);
}
// But swipe the contentView
swipeContent(position, pageWidth, contentView1);
// Counteract the default swipe
view.setTranslationX(pageWidth * -position);
} else if (position <= 1) { // (0,1]
// This page is moving in from the right
// Counteract the default swipe
view.setTranslationX(pageWidth * -position);
swipeContent(position, pageWidth, contentView1);
if (backgroundImageView != null) {
// Fade the image out
backgroundImageView.setAlpha(ALPHA_VALUE - position);
}
} else {
// This page is way off-screen to the right
}
contentView1.bringToFront();
}
private void swipeContent(float position, int pageWidth, View view) {
if (view != null) {
view.setTranslationX(pageWidth * position);
}
}
}
The initialization of viewpager and transformer looks like this:
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setPageTransformer(false, new CustomPageTransformer());
pagerAdapter = new ItemPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(1);
pagerAdapter.setItems(items);
You can find the full source code here.
After a lot of digging I changed the "contentView1" a little bit so I set the background on the viewpager and the contentView1´s background to transparent. I also set the level of ALPHA to 0.6f.
public static final float ALPHA_VALUE = 0.6f;
That made it a lot better.
I'm using a TranslateAnimation to make a fragment (GoogleMap) sliding down to give space to an EditText and a TextView to be visible.
so I used this:
text: TextView
edit: EditText
MapLayout: a LinearLayout that contains the Map
Animation animation = new TranslateAnimation(
MapLayout.getX(), MapLayout.getY(),MapLayout.getY(), text.getHeight()+edit.getHeight());
The problem is that I can't make the slide because text.getHeight()+edit.getHeight() returns 0 so there's no slide!
I tried using a number (100 for exemple), the slide is made, but it's different between the devices, I tested on a Galaxy S3 and the slide is not complete, there's still a part of the EditText which is not visible, as for the emulator it worked ok.
When I tried to make the number a bit bigger, so the slide will be longer (200 for exemple), well... the slide was good for the S3, but i was big for the emulator.
So what I want to know is that if there's any way to make the slide move to a point, without depending on the device, I mean without using pixels; so the slide will work perfectly in any device/
I hope that my problem is clear.
Thank you
Update: I don't if this will help, I added a Toast message, show the height of the EditText and the TextView, in the Emulator it says: 85 and in the S3 it says 181
So yeah, I need to make the map slide down in any device like I said
MainActivity:
protected Animation animation;
protected LinearLayout MapLayout;
protected EditText edit;
protected TextView text;
MapLayout = (LinearLayout)findViewById(R.id.MapLayout);
edit = (EditText)findViewById(R.id.Recherche);
text = (TextView)findViewById(R.id.CaptionRecherche);
Toast.makeText(context, "Height: "+(edit.getHeight()+text.getHeight()), 1000).show();
animation = new TranslateAnimation(MapLayout.getX(), MapLayout.getY(), MapLayout.getY(), text.getHeight()+edit.getHeight());
animation.setDuration(1000);
animation.setFillAfter(true);
MapLayout.startAnimation(animation);
Main XML:
------- I'm using a DrawerLayout...I have a slide menu tu show in the application...just for your information-------
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/DrawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include
android:id="#+id/ContenuPrincipal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="#layout/activity_main_relative"
/>
<!-- ListView... La liste des options du menu -->
<ListView
android:id="#+id/Menu"
android:layout_width="250dp"
android:layout_height="fill_parent"
android:choiceMode="singleChoice"
android:layout_gravity="start"
android:background="#333"
android:divider="#666"
android:dividerHeight="1dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
/>
</android.support.v4.widget.DrawerLayout>
Main2 XML (The one I included above):
<?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="#E8E8E8">
<!-- Champs de saisie pour effectuer la recherche: -->
<TextView
android:id="#+id/CaptionRecherche"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Entrer l'emplacement que vous cherchez: "
android:textSize="20sp"
android:layout_marginTop="7dp"
android:layout_marginLeft="20dp"
/>
<EditText
android:id="#+id/Recherche"
android:layout_width="250dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:hint="Salle, Deparetement..."
android:layout_marginLeft="20dp"
android:layout_marginBottom="20dp"
android:maxLength="100"
android:maxLines="1"
android:layout_below="#id/CaptionRecherche"/>
<!-- La map: -->
<LinearLayout
android:id="#+id/MapLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
</RelativeLayout>
As a part of my application, I have a status bar which contains some text. This status bar is hidden until the user clicks a button at which point it slides down (hiding the topmost content of the layout below).
The code I use to get the correct height of the hidden status bar:
private int hiddenStatusHeight;
private int currentStatusBarHeight;
private void getStatusBarHeight() {
final ViewTreeObserver observer = hiddenStatus.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi") #SuppressWarnings("deprecation") #Override public void onGlobalLayout() {
hiddenStatus.measure(MeasureSpec.UNSPECIFIED,
MeasureSpec.UNSPECIFIED);
hiddenStatusHeight = hiddenStatus.getMeasuredHeight();
currentStatusBarHeight = statusBar.getHeight();
ViewTreeObserver obs = hiddenStatus.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
}
The code that is executed when the button is clicked:
private OnClickListener ExpandClickListener = new OnClickListener() {
#Override public void onClick(View v) {
boolean isExpanded = (Boolean) expandButton
.getTag(R.id.TAG_EXPANDED);
int originalHeight = (Integer) expandButton
.getTag(R.id.TAG_ORIGINAL_HEIGHT);
if (isExpanded) {
expandButton.setTag(R.id.TAG_EXPANDED, false);
expandButton.setImageResource(R.drawable.ic_action_down);
// statusBar.setLayoutParams(new FrameLayout.LayoutParams(
// LayoutParams.MATCH_PARENT, originalHeight));
Log.d(TAG, "Collapsing to " + originalHeight);
ValueAnimator va = ValueAnimator.ofInt(currentStatusBarHeight,
originalHeight);
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
statusBar.getLayoutParams().height = value.intValue();
statusBar.requestLayout();
}
});
va.start();
} else {
expandButton.setTag(R.id.TAG_EXPANDED, true);
expandButton.setImageResource(R.drawable.ic_action_collapse);
currentStatusBarHeight = originalHeight + hiddenStatusHeight;
// statusBar.setLayoutParams(new FrameLayout.LayoutParams(
// LayoutParams.MATCH_PARENT, currentStatusBarHeight + 15));
Log.d(TAG, "Expanding to " + originalHeight + "+"
+ hiddenStatusHeight + "=" + currentStatusBarHeight);
ValueAnimator va = ValueAnimator.ofInt(originalHeight,
currentStatusBarHeight);
va.setDuration(500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
statusBar.getLayoutParams().height = value.intValue();
statusBar.requestLayout();
}
});
va.start();
}
}
};
And finally my layout XML (it has to be a FrameLayout):
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="70dp" >
<LinearLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp"
android:showDividers="middle" >
</LinearLayout>
</ScrollView>
<RelativeLayout
android:id="#+id/displayStatusBar"
style="#style/DisplayStatusBar"
android:layout_width="match_parent"
android:layout_height="65dp" >
<RelativeLayout
android:id="#+id/status_always_visible"
style="#style/StatusBar"
android:layout_width="match_parent"
android:layout_height="20dp" >
<TextView
android:id="#+id/status_received"
style="#style/StatusBarText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/received" />
<TextView
android:id="#+id/status_time_received"
style="#style/StatusBarText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/status_received" />
<TextView
android:id="#+id/status_time_delete_relative_text"
style="#style/StatusBarText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/status_time_delete_relative"
android:text="#string/is_deleted" />
<TextView
android:id="#+id/status_time_delete_relative"
style="#style/StatusBarText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/minutes" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/status_hidden"
style="#style/StatusHidden"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/status_always_visible" >
<LinearLayout
android:id="#+id/status_hydrants_near_address_container"
style="#style/StatusHiddenText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:divider="#android:drawable/divider_horizontal_bright"
android:orientation="vertical"
android:paddingLeft="10dp"
android:showDividers="middle" >
<TextView
style="#style/StatusHiddenText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_information" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="#+id/optionsBar"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#999"
android:orientation="horizontal"
android:paddingTop="5dp" >
<ImageButton
android:id="#+id/button_hydrants"
style="#style/android:Widget.ImageButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:alpha="50"
android:contentDescription="#string/module_hydrants"
android:src="#drawable/ic_action_place" />
<ImageButton
android:id="#+id/button_route"
style="#style/android:Widget.ImageButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:contentDescription="#string/module_directions"
android:src="#drawable/ic_action_directions" />
<ImageButton
android:id="#+id/button_pdf"
style="#style/android:Widget.ImageButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:clickable="false"
android:contentDescription="#string/module_accessplan"
android:src="#drawable/ic_action_attachment" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageButton
android:id="#+id/button_more"
style="#style/android:Widget.ImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_action_down" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<!-- The "empty" view to show when there are no items in the "list" view defined above. -->
<TextView
android:id="#android:id/empty"
style="?android:textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="32dp"
android:text="#string/no_information"
android:textColor="?android:textColorSecondary" />
</FrameLayout>
Hope some of this may be helpful to you.
Just to mention it, I have asked a similar question where the visible layout is pushed downwards as the menu expands. So have a look at that if you rather want this behaviour: How to animate a slide in notification view that pushes the content view down
Happy coding
I'm trying to create a fragment that lays out a series of custom views dynamically. The main content for this layout is a RelativeLayout nested in a LinearLayout (to center it horizontally), nested in a ScrollView.
The RelativeLayout has a few TextViews and a 9 patch ImageView that is meant to scale with the dynamically added custom views. However, the image (achievements_bgImageView below) is ending up as the size of the screen, and is not respecting the size of its parent RelativeLayout even after I've added the appropriate amount of custom views. The image scales fine when I manually set the size of achievements_mainLayout (see the commented out lines below), but does nothing if I try to let that RelativeLayout's wrap_content handle its own sizing.
The ScrollView IS respecting the size of the RelativeLayout, as all the content is present, it's simply the imageView that isn't stretching to match the content at this point.
Any help would be appreciated... My manual calculations don't seem to be good enough to account for different devices, despite the fact I'm accounting for screen density and I'm manually forcing the RelativeLayout to a constant width.
It's worth noting that the measured size of the RelativeLayout is always equal to the height of the screen, regardless of whether or not the sum of its content is greater or less than that height. So, essentially, WRAP_CONTENT is simply not doing what it's supposed to be doing. I have nothing referencing any edge of of the RelativeLayout, so circular dependencies shouldn't be a problem.
fragment_achievements.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<RelativeLayout
android:layout_width="320dp"
android:layout_height="wrap_content"
android:id="#+id/achievements_mainLayout">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/achievements_bgImageView"
android:src="#drawable/bkg_achievements9"
android:adjustViewBounds="true"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
android:layout_centerHorizontal="true"
android:scaleType="fitXY"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name Field"
android:id="#+id/achievements_nameTextView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="28dp"
android:layout_marginTop="30dp"/>
<ImageView
android:layout_width="52dp"
android:layout_height="52dp"
android:id="#+id/achievements_avatarImageView"
android:layout_below="#+id/achievements_nameTextView"
android:layout_alignLeft="#+id/achievements_nameTextView"
android:src="#drawable/achieve_avatar"
android:layout_marginTop="5dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Top Moment:"
android:id="#+id/textView2"
android:layout_alignBottom="#+id/achievements_avatarImageView"
android:layout_toRightOf="#+id/achievements_avatarImageView"
android:layout_marginBottom="16dp"
android:layout_marginLeft="4dp"
android:textSize="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Me Overall:"
android:id="#+id/textView3"
android:layout_alignTop="#+id/textView2"
android:layout_alignLeft="#+id/textView2"
android:layout_marginTop="16dp"
android:textSize="12dp"/>
<TextView
android:layout_width="52dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="153"
android:id="#+id/achievements_totalPointsTextView"
android:gravity="center"
android:layout_alignTop="#+id/achievements_avatarImageView"
android:layout_alignRight="#+id/achievements_bgImageView"
android:layout_alignEnd="#+id/achievements_bgImageView"
android:layout_marginRight="31dp"
android:textColor="#f7a033"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Moment"
android:id="#+id/achievements_topMomentTextView"
android:layout_alignTop="#+id/textView2"
android:layout_toRightOf="#+id/textView2"
android:layout_marginLeft="5dp"
android:textSize="12dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="153"
android:id="#+id/achievements_overallTextView"
android:layout_alignTop="#+id/textView3"
android:layout_toRightOf="#+id/textView3"
android:layout_marginLeft="5dp"
android:textSize="12dp"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
AchievementFragment.java
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = null;
fragmentView = inflater.inflate(R.layout.fragment_achievements, container, false);
ImageView avatarImageView = (ImageView)fragmentView.findViewById(R.id.achievements_avatarImageView);
...
// Basic Achievement List Setup
RelativeLayout mainLayout = (RelativeLayout)fragmentView.findViewById(R.id.achievements_mainLayout);
AchievementRow currentRow = null;
List achievementTypeList = CampaignManager.sharedManager().sortedAchievementTypeList();
int achievementCount = achievementTypeList.size();
for (int i = 0; i < achievementCount; i++) {
AchievementType achievementType = (AchievementType)achievementTypeList.get(i);
// Every third achievement creates a new row.
if ((i % 3) == 0) {
AchievementRow row = (AchievementRow)inflater.inflate(R.layout.widget_achievementrow, null);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (currentRow == null) {
layoutParams.addRule(RelativeLayout.BELOW, avatarImageView.getId());
layoutParams.setMargins(10, 70, 10, 0);
} else {
layoutParams.addRule(RelativeLayout.BELOW, currentRow.getId());
layoutParams.setMargins(10, 10, 10, 0);
}
layoutParams.addRule(RelativeLayout.ALIGN_LEFT, backgroundImageView.getId());
layoutParams.addRule(RelativeLayout.ALIGN_RIGHT, backgroundImageView.getId());
row.setLayoutParams(layoutParams);
row.setId(i+1);
mainLayout.addView(row);
currentRow = row;
}
// Now setup the Button
AchievementButton achievementButton = currentRow.buttonForIndex(i % 3);
achievementButton.achievementType = achievementType;
achievementButton.setOnClickListener(achievementButtonListener);
achievementButton.setVisibility(View.VISIBLE);
CacheManager.sharedManager().fetchAchievementThumbnail(getActivity(), achievementButton, achievementType);
}
// This is the manual scaling of mainLayout
// float scale = getResources().getDisplayMetrics().density;
// float headerHeight = scale * 150.0f;
// float rowHeight = scale * 78.0f;
// ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
// mainLayoutParams.height = (int)(headerHeight + (Math.ceil(achievementCount / 3.0) * rowHeight));
return fragmentView;
}
Try calling requestLayout on the children.
I recently had a similar problem and was similarly frustrated that things like invalidate and requestLayout seemed to do nothing. What I didn't understand is that requestLayout doesn't propagate down to its children; it propagates up to its parents. To re-measure something that was previously measured, I had to call requestLayout on the View that changed rather than the View I actually wanted to resize.
Android does NOT refresh layout of views with "wrap_content" once it has been displayed.
So if you add a child view, or modify the content dynamically, you're screwed.
I do agree that this is a nightmare and a real flaw in Android UI!
To solve that, I've written a static class that recomputes the sizes and forces the update of the layout for the views with "wrap_content"
The code and instructions to use are available here:
https://github.com/ea167/android-layout-wrap-content-updater
Enjoy!
A simple way to update the size of a View with WRAP_CONTENT is change the visibility to GONE and back to the old visibility.
int visibility = view.getVisibility();
view.setVisibility(View.GONE);
view.setVisibility(visibility);
TESTED ON ANDROID JELLY BEAN IN 2014
MAY NOT WORK ON NEWER ANDROID VERSIONS
Ok, I solved this by manually measuring the RelativeLayout immediately after adding all the views and setting the mainLayoutParams height explicitly. I wish I was smarter and knew why it wasn't automatically doing this correctly in the first place, but oh well.
...
mainLayout.measure(0, 0);
ViewGroup.LayoutParams mainLayoutParams = mainLayout.getLayoutParams();
mainLayoutParams.height = mainLayout.getMeasuredHeight() + 10;
...
I encountered same issue when working with LinearLayout which has wrap_content and one child as TextView match_parent.
To fix this I did this:
Remove the TextView programatically and then add it again.
linearLayout.removeView(textView)
linearLayout.addView(textView)
I know it sounds stupid but it works.
In my case calling invalidate didn't work, only this worked.
Depending on your implementation you need to take care of view index inside its parent
You are getting this problem because you set your layout first and then add its content dynamically.
You are telling the layout to wrap to the content that is not yet their. Try using your layout inflater after you have grabbed your content
You should use NestedScrollView Instead of simple scrollview.
here is my sample Activity Layout code
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabIndicatorHeight="6dp"
android:layout_marginTop="-10dp"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<wsit.rentguru.utility.CustomViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
here is code for custom viewpager
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
setup function for viewpager in the activity
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new SampleFragment(), " ");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
here is the sample SampleFragment layout code
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F0ECE6"
android:fillViewport="true"
android:scrollbars="vertical"
android:animateLayoutChanges="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0ECE6"
android:focusableInTouchMode="true"
>
<Spinner
android:id="#+id/product_category"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:paddingLeft="10dp"
android:drawableRight="#drawable/ic_down_arrow"
/>
<Spinner
android:id="#+id/product_sub_category"
android:layout_below="#+id/product_category"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center|left"
android:visibility="gone"
android:paddingLeft="10dp"
android:background="#android:color/white"
android:drawableRight="#drawable/ic_down_arrow"
/>
<EditText
android:id="#+id/product_title"
android:layout_below="#+id/product_sub_category"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp"
android:background="#android:color/white"
android:hint="PRODUCT TITLE"
android:singleLine="true"
android:imeOptions="actionDone"
android:layout_width="match_parent"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_height="40dp" />
<LinearLayout
android:id="#+id/availability_layout"
android:layout_below="#+id/product_title"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/availability"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<Button
android:id="#+id/from"
android:background="#android:color/white"
android:hint="FROM"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textStyle="normal"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginRight="10dp"/>
<Button
android:id="#+id/to"
android:background="#android:color/white"
android:hint="TO"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/product_location_layout"
android:layout_below="#+id/availability_layout"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/product_location"
android:textStyle="bold"
android:paddingBottom="10dp"
android:textSize="14sp"
/>
<Spinner
android:id="#+id/state_spinner"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/edittext_rectangle_box"
android:gravity="center|left"
android:textSize="14sp"
android:layout_marginBottom="10dp"
android:drawableRight="#drawable/ic_down_arrow"
android:paddingLeft="10dp"
/>
<EditText
android:id="#+id/area"
android:background="#android:color/white"
android:hint="Area"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="match_parent"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginBottom="10dp"
/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<EditText
android:id="#+id/zipCode"
android:background="#android:color/white"
android:hint="Zip Code"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:singleLine="true"
android:imeOptions="actionNext"
android:layout_marginRight="10dp"/>
<EditText
android:id="#+id/city"
android:background="#android:color/white"
android:hint="City"
android:layout_weight="1"
android:gravity="center|left"
android:padding="10dp"
android:textSize="14sp"
android:singleLine="true"
android:imeOptions="actionDone"
android:textColorHint="#000000"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="#+id/tab1_next"
android:layout_width="150dp"
android:layout_height="40dp"
android:text="NEXT"
android:layout_below="#+id/product_location_layout"
android:layout_margin="20dp"
android:layout_alignParentRight="true"
android:background="#color/next_button"
android:textColor="#android:color/white"
android:layout_marginBottom="20dp"
/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
Set the layout parameters again(width and height), right after adding the view. This worked for me.
if the parent View is a FrameLayout, then do something like this:
ImageView view = (ImageView) LayoutInflater.from(activity).inflate(R.layout.image_object_view, null);
imageObjectsHolder.addView(view);
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(param);
My problem was fixed by seting layout_width to some specific dp.
So changing from "wrap content" or "match parent"
to
android:layout_width="300dp"
will fix it, but i know it's not solution for all cases. But maybe you have some parent width, so you can apply the width to the textview.
height leave with wrap_content, and it will work.