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.
Related
I am trying to implement vertical view pager like "Happn" app
Here is my custom ViewPager class
VerticalViewPager.java
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
I am able to show vertical view pager. But I am not able to maintain page margin on top, So that adjacent items also can partially visible. Below setPageMargin() method is working for horizontal viewpager. I want similar gaping in vertical view pager. Please help me, I am really struck.
mPager.setPageMargin(-100);
Try this below code
viewPager.setClipToPadding(false);
viewPager.setPadding(70, 30, 170, 30);//left,top,right,bottom in px
viewPager.setPageMargin(30);
This will set the padding as desired, this one is working for me.
Try it and do let me know if it worked for you
**my viewpager 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:background="#color/dim_white"
android:layout_height="match_parent">
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/card_view"
style="#style/CardStyle.ContactList"
android:layout_width="match_parent"
android:layout_marginBottom="60dp"
android:layout_marginTop="60dp"
android:layout_marginLeft="22dp"
android:layout_marginRight="22dp"
app:cardCornerRadius="20dp"
android:layout_height="match_parent">
<ImageView
android:id="#+id/profile_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:src="#drawable/logo_3_1" />
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="80dp"
android:gravity="center_horizontal"
android:text="Sardar"
android:textColor="#color/white"
android:textSize="#dimen/letter_large" />
</android.support.v7.widget.CardView>
</FrameLayout>
**My parent layout :**
<RelativeLayout 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="wrap_content"
android:orientation="vertical"
">
<RelativeLayout
android:id="#+id/empty_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/dim_white"
android:visibility="gone">
<ImageView
android:id="#+id/add_photo"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:src="#drawable/favpholder"
android:textSize="#dimen/verify_phone_number_text_size" />
<TextView
android:id="#+id/no_fav_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/add_photo"
android:layout_marginLeft="#dimen/spacing_24_dp"
android:layout_marginTop="#dimen/spacing_medium"
android:layout_marginRight="#dimen/spacing_24_dp"
android:gravity="center"
android:text="#string/no_followers"
android:textAlignment="center"
android:textAppearance="#style/TextStyle.Medium"
android:textColor="#color/slate"
android:textSize="#dimen/letter_large" />
</RelativeLayout>
<android.support.v7.widget.CardView
android:id="#+id/search_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/search_bar_height"
android:layout_below="#id/empty_layout"
android:layout_margin="#dimen/spacing_medium">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/search_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/spacing_small"
android:src="#drawable/ic_search_black_24dp" />
<TextView
android:id="#+id/search_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_margin="#dimen/spacing_xsmall"
android:layout_toEndOf="#id/search_icon"
android:gravity="center"
android:text="#string/search_contacts" />
</RelativeLayout>
</android.support.v7.widget.CardView>
<custom.VerticalViewPager
android:layout_below="#id/search_bar"
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
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 navigation Drawer, the left side is the left navigation drawer, containing TextView "detailsTxt". This contains dynamic text, and I want the navigation drawer to be resized to fit the TextView when the user opens the drawer.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout mlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/app_bg">
<LinearLayout
android:id="#+id/topNavigator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#drawable/toolbar_white_space">
<TextView
android:id="#+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:background="#android:color/transparent"
android:text="Ayman Salah"
android:textColor="#android:color/white"
android:textSize="16sp"
android:textStyle="bold|italic"
android:layout_marginTop="15dp" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>
<!-- drawer layout -->
<LinearLayout
android:layout_width="450dp"
android:id="#+id/leftBar"
android:layout_gravity="start"
android:layout_height="fill_parent"
android:gravity="start|left">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/nbackground">
<TextView
android:id="#+id/detailsTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:textSize="20sp"
android:text="string/sample_details"
android:textColor="#android:color/widget_edittext_dark" />
</RelativeLayout>
</LinearLayout>
Add listeners for Drawer
Open/Close events
and
Add this code in onDrawerOpen(), found from this answer :
LinearLayout mDrawerListView = (LinearLayout) findViewById(R.id.leftBar);
mDrawerListView.post(new Runnable() {
#Override
public void run() {
DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) mDrawerListView.getLayoutParams();
params.width = (int) 100; // for example
mDrawerListView.setLayoutParams(params);
}
});
and set layout_width="0dp" in xml file
Try initializing the Navigation Draw with a zero width, i.e. android:layout_width="0dp", and then execute the snippet below in your onCreate(Bundle savedInstanceState).
// Programatically assigns a custom width to a DrawerLayout.
this.getDrawerLayout().addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
/** Fire-and-forget programmatic width implementation for the DrawerLayout. */
#Override public final void onDrawerSlide(final View pDrawerView, final float pSlideOffset) {
// Recalculate the new LayoutParams.
pDrawerView.setLayoutParams(this.getLayoutParams((DrawerLayout.LayoutParams)pDrawerView.getLayoutParams()));
// Stop listening for future events, once we've configured the size once. (We know the DrawerLayout is the direct parent of the DrawerView.)
((DrawerLayout)pDrawerView.getParent()).removeDrawerListener(this);
}
/** A method used to define the new LayoutParams of the DrawerView. */
private final DrawerLayout.LayoutParams getLayoutParams(final DrawerLayout.LayoutParams pLayoutParams) {
/** TODO: Compute your width here! (i.e pLayoutParams.width = X) **/
// Return the LayoutParams.
return pLayoutParams;
}
});
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:
i'm struggling with scrollview.
I want to display content (1) then buttons (2) and finally content (3).
When i'm scrolling, i want the buttons to be fixed at the top of my activity.
I can't post image, so it would be :
1
2
3
I scroll
2 (fixed at top)
3 (this part start to scroll when the 1 disapear at top)
I scroll
2 (fixed at top)
3 (still scrollable).
I m curently using this :
<ScrollView
android:id="#+id/sv_entete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/layout_bar"
android:background="#color/gris_blanc" >
<RelativeLayout
android:id="#+id/layout_conteneur"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
// Some image etc.
</RelativeLayout>
</ScrollView>
<Button
android:id="#+id/btn_presentation_has_to_stay_on_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/sv_entete" />
<Button
android:id="#+id/btn_analyze_has_to_stay_on_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/sv_entete" />
<ScrollView
android:id="#+id/sv_presentation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/btn_presentation"
android:background="#color/gris_blanc" >
<RelativeLayout
android:id="#+id/layout_presentation"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
// Some image etc
</RelativeLayout>
</ScrollView>
But only the second part scroll (3), the first part (1) is (obviously) not linked with the second scrollview, but i can't figured out by myself.
Any help plz ?
Looks like there's no way to implement it right out of the box. So, You need to create custom components.
Unfortunately, there's not much details in the question, so I'm not able to suggest which way is better for your case.
However, below two variants I can think of:
Have two button panels in the same layout. Initially only one panel should be visible (one inside scroll view). During scrolling, it first panel reaches top, You'll need to make second one visible. And make it invisible, when scroll up (and first one become visible inside ScrollView). It would increase complexity of layout and coe little bit (e.g. You'll need to listen two sets of buttons instead of one). In simple test application I haven't observed any critical issues / UI artifacts using this implementation,
For that you need to create separate layout for buttons panel, e.g. buttons_panel.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/btn_presentation_has_to_stay_on_top"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="left button"/>
<Button
android:id="#+id/btn_analyze_has_to_stay_on_top"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="right button"/>
</LinearLayout>
Then main activity layout might look like the following (activity_main.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.alexstarc.testapp.ObservableScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/sv_entete">
<RelativeLayout
android:id="#+id/layout_conteneur"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="#+id/image_1"
android:layout_alignParentTop="true"
android:background="#android:color/holo_blue_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 1"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/image_1_1"
android:layout_centerHorizontal="true"
android:layout_below="#id/image_1"
android:src="#drawable/img1"/>
<include
layout="#layout/buttons_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/middle_button_panel"
android:layout_below="#id/image_1_1" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/image_2"
android:layout_below="#id/middle_button_panel"
android:background="#android:color/holo_green_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 2"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="350dp"
android:id="#+id/image_3"
android:layout_below="#id/image_2"
android:src="#drawable/img3"/>
<TextView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/image_4"
android:layout_below="#id/image_3"
android:background="#android:color/holo_orange_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 4 (1)"/>
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/image_5"
android:layout_below="#id/image_4"
android:background="#android:color/holo_purple"
android:gravity="center"
android:textSize="30sp"
android:text="Image 5"/>
<TextView
android:layout_width="match_parent"
android:layout_height="350dp"
android:id="#+id/image_6"
android:layout_below="#id/image_5"
android:background="#android:color/holo_blue_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 6"/>
<TextView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/image_7"
android:layout_below="#id/image_6"
android:background="#drawable/img1"
android:gravity="center"
android:textSize="30sp"
android:text="Image 7"/>
<TextView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/image_8"
android:layout_below="#id/image_7"
android:background="#android:color/holo_orange_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 8"/>
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/image_9"
android:layout_below="#id/image_8"
android:background="#android:color/holo_purple"
android:gravity="center"
android:textSize="30sp"
android:text="Image 9"/>
<TextView
android:layout_width="match_parent"
android:layout_height="350dp"
android:id="#+id/image_10"
android:layout_below="#id/image_9"
android:background="#android:color/holo_blue_dark"
android:gravity="center"
android:textSize="30sp"
android:text="Image 10"/>
<TextView
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/image_11"
android:layout_below="#id/image_10"
android:background="#drawable/img1"
android:gravity="center"
android:textSize="30sp"
android:text="Image 11"/>
</RelativeLayout>
</com.alexstarc.testapp.ObservableScrollView>
<include
layout="#layout/buttons_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/top_button_panel"
android:layout_alignParentTop="true"
android:visibility="gone" />
</RelativeLayout>
There's special custom ViewGroup - ObservableScrollView. It's needed, because ScrollView doesn't have any listeners for observing scroll position, but we need to detect then buttons panel inside it become visible. Here's its draft code (please note, I haven't done any optimization or full testing):
public class ObservableScrollView extends ScrollView {
private int mTrackViewId = 0;
private View mTrackView = null;
private int mTrackViewTop = 0;
private int mTrackViewDown = 0;
private OnViewReachTop mTopReachListener = null;
/* Helper interface to notify listener about */
public interface OnViewReachTop {
/**
* Called then View riches top
*/
void onReachTop();
/**
* Called then view leaves top position
*/
void onLeaveTop();
}
public ObservableScrollView(final Context context) {
super(context);
}
public ObservableScrollView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public ObservableScrollView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets view id to be tracked and corresponding callback
*
* #param viewId id of view to be trackked
* #param listener {#link com.alexstarc.testapp.ObservableScrollView.OnViewReachTop} to be called
*/
public void setViewTopTracking(final int viewId, final OnViewReachTop listener) {
mTrackView = findViewById(viewId);
if (mTrackView == null) {
throw new IllegalArgumentException("Passed view id should be from child of this scroll view");
}
mTrackViewId = viewId;
mTopReachListener = listener;
}
#Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
if (mTrackViewDown == 0 && mTrackViewTop == 0) {
mTrackViewDown = mTrackView.getBottom();
mTrackViewTop = mTrackView.getTop();
}
super.onScrollChanged(l, t, oldl, oldt);
if (getScrollY() >= mTrackViewTop) {
mTopReachListener.onReachTop();
} else if (getScrollY() <= mTrackViewDown) {
mTopReachListener.onLeaveTop();
}
}
}
And activity code, which will observe current scroll position and show / hide second buttons panel:
public class MyActivity extends Activity implements ObservableScrollView.OnViewReachTop {
private static final String TAG = "MyActivity";
private View mButtonsPanel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonsPanel = findViewById(R.id.top_button_panel);
((ObservableScrollView)findViewById(R.id.sv_entete)).setViewTopTracking(R.id.middle_button_panel, this);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.action_bar, menu);
return true;
}
#Override
public void onReachTop() {
mButtonsPanel.setVisibility(View.VISIBLE);
}
#Override
public void onLeaveTop() {
mButtonsPanel.setVisibility(View.GONE);
}
}
Second way: take ScrollView code, analyze it and make possible to fix some view on the top. This way is more complex, but possible to implement. Please, investigate it (if first one is not applicable to your code / layout) and ask additional questions if face some particular problems with it.