Animation, swipe image over another image - android

How can I implement swipe of one image on another likewise the attached image.
In image one can see that background image is static, and user can able to swipe another image. Its a screenshot of housing.com app.
Can anyone help me in this.
Note: tried for viewpager, jazzyviewpager, Parallex view but no success

Use custom Viewpager(jazzy viewpager library with stack effect and disable zoomout functionality inside this) to acheive this.

So after so many days of search n implementations I got this exactly.
Steps to achieve:
1. Implement Viewpager.
2. User custom view pager with transition.
3. The most important one, Implement clipDrawable to clip drawable on upcoming page on view pager.
Here is the Scale transformation class uses clipdrawable :
public class ScalePageTransformer implements PageTransformer {
private static final float SCALE_FACTOR = 0.95f;
private final ViewPager mViewPager;
public ScalePageTransformer(ViewPager viewPager) {
this.mViewPager = viewPager;
}
#Override
public void transformPage(View page, float position){
View mainLayout = page.findViewById(R.id.bg_rel);
ClipDrawable clipDrawable = (ClipDrawable) mainLayout.getBackground();
if (position <= 0){
// apply zoom effect and offset translation only for pages to
// the left
// final float transformValue = Math.abs(Math.abs(position) - 1) * (1.0f - SCALE_FACTOR) + SCALE_FACTOR;
int pageWidth = mViewPager.getWidth();
final float translateValue = position* -pageWidth;
// page.setScaleX(transformValue);
// page.setScaleY(transformValue);
if (translateValue > -pageWidth){
page.setTranslationX(translateValue);
} else {
page.setTranslationX(0);
}
clipDrawable.setLevel(10000);
} else {
//entering view
int level = (int) ((1 - position) * 10000);
clipDrawable.setLevel(level);
mainLayout.setTranslationX(-1 * position * page.getWidth());
}
}
}
rel_bg: My main layout having drawables.
Hope it helps for somebody.

Related

ViewPager with left and right preview

I need to set up a ViewPager with the following requirements:
- at any given time, 3 pages must be visible in the screen
- the center page isn't scaled and the behind pages are 60% of the center page;
- center page, must overlap a bit the behind pages.
From what I saw in other questions I've tried to do this:
viewPager.setClipToPadding(false);
int padding = (metrics.widthPixels - centerViewSize) / 2;
viewPager.setPadding(padding, 0, padding, 0);
viewPager.setPageMargin(-(padding / 2));
viewPager.setCurrentItem(10);
viewPager.setOffscreenPageLimit(3);
Doing this got me here:
This is what I was expecting. Just need to bring to front the current selected item.
I've then tried to scale the view with:
public static final float SCALED_SIZE = 0.6f;
viewPager.setPageTransformer(false, new PageTransformer() {
#Override
public void transformPage(final View page, final float position) {
if (position < -1) {
page.setScaleX(SCALED_SIZE);
page.setScaleY(SCALED_SIZE);
} else if (position <= 1) {
float scaleFactor = Math.max(SCALED_SIZE, 1 - Math.abs(position));
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
} else {
page.setScaleX(SCALED_SIZE);
page.setScaleY(SCALED_SIZE);
}
}});
But that gives me some problems.
The first item that should be selected is not the correct one.
Animation chopy.
At some points, there are more than 3 pages on the screen.
Scale is from the bottom and I would like to be from the center.
Any idea how I can solve my issues?
use Library UltraViewPager. It have very nice effects.

Sliding view used to control ViewPager paging

My goal is to have a sliding view on fragment 1 which slides a set distance before fragment 2 is pulled into visual view.
I made a visual here that shows what I am trying to do:
Pic 1 Shows the default view of fragment 1 (pink) and sliding view (green), nothing has happened in this state.
Pic 2 The sliding view is able to slide to it's cutoff (black line). It cannot move past this on this fragment.
Pic 3 The entire fragment 1 begins to slide, fragment 2 (blue) is now starting to be pulled into the view
Pic 4 Both fragments continue to slide as before.
Pic 5 Fragment 2 has now slid into view.
When the user tries to return to the previous screen the transition happens in reverse.
Right now I have implemented a ViewPager which hosts the fragments 1 and 2. The default ViewPager behavior allows me to slide between the two fragments, but I am unsure how to implement the functionality I have described.
I was able to achieve the desired transition with the use of a ViewPager PageTransformer
I am using Xamarin.Android in my project, so C# is used. Although this snippet is in C# it could easily be ported to Java code for use in other projects.
float passpoint = 7/8f;
public void TransformPage(View view, float position)
{
var pageWidth = view.Width;
var slidingGap = pageWidth - pageWidth * passpoint;
var translation = position * pageWidth;
if (position < -1)
{ // [-Infinity,-1)
// This page is way off-screen to the left.
view.Alpha = 0;
}
else if (position <= 1)
{ // [-1,1]
var r = new Rect();
//if valid, this view is the startpage
Button button = (Button)view.FindViewById(Resource.Id.slidingButton);
if (button != null)
{
var posPassPoint = -(1 - passpoint);
float ratio;
//create sliding gap
if (position > posPassPoint)
{
ratio = RatioBetween(position, posPassPoint, 0);
button.TranslationX = slidingGap * -ratio;
}
//compensate for sliding gap after it has been reached
else
{
//1- bc want the ratio to shrink
ratio = 1-RatioBetween(position, -1, posPassPoint);
}
view.TranslationX = slidingGap * ratio;
}
//valid on views other than start page (no sliding button)
if (button == null)
{
float ratio;
//create sliding gap
if (position >= passpoint)
ratio = RatioBetween(position, passpoint, 1);
//compensate for sliding gap after it has been reached
else
ratio = 1 - RatioBetween(position, 0, passpoint);
view.TranslationX = slidingGap * ratio;
}
}
else
{ // (1,+Infinity]
// This page is way off-screen to the right.
view.Alpha = 0;
}
}
float RatioBetween(float input, float upperBound, float lowerBound)
{
return (input - lowerBound) / (upperBound - lowerBound);
}

ListView overlay another layout when scroll

Actually I don't know how it properly called - overlay, parallax or slideUP, whatever, I have an Activity called "cafe details" which presents a Container(LinearLayout) with header information (name, min price, delivery time min e.t.c) and other container (ViewPager) which contains a ExpandableListView with something information (menus&dishes) and all I want to do is slide up my Viewpager when scrolls listview to scpecific Y position to cover(or overlay) header information.
A similar effect (but with parallax that I don't need to use) looks like this
I can detect when user scrolling listview down or up but how I can move container with ViewPager to overlay other container? Please give me ideas, regards.
UPD
I have tried a huge number of ways how to implement it and all of them unfortunately are not suitable. So now I have come to next variant - add scroll listener to ListView, calculate scrollY position of view and then based on that move the viewpager on y axis by calling setTranslationY();
Here is some code
1) ViewPager's fragment
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
if (getActivity() != null) {
((MainActivity) getActivity()).resizePagerContainer(absListView);
}
}
});
2) MainActivity
//object fields
int previousPos;
private float minTranslation;
private float minHeight;
<--------somewhere in onCreate
minTranslation = - (llVendorDescHeaders.getMeasuredHeight()+llVendorDescNote.getMeasuredHeight());
//llVendorDescHeaders is linearLayout with headers that should be hidden
//lVendorDescNote is a textView on green background;
minHeight = llVendorDescriptionPagerContainer.getMeasuredHeight();
//llVendorDescriptionPagerContainer is a container which contains ViewPager
--------->
public void resizePagerContainer(AbsListView absListView){
final int scrollY = getScrollY(absListView);
if (scrollY != previousPos) {
final float translationY = Math.max(-scrollY, minTranslation);
llVendorDescriptionPagerContainer.setTranslationY(translationY);
previousPos = scrollY;
}
}
private int getScrollY(AbsListView view) {
View child = view.getChildAt(0);
if (child == null) {
return 0;
}
int firstVisiblePosition = view.getFirstVisiblePosition();
int top = child.getTop();
return -top + firstVisiblePosition * child.getHeight() ;
}
This simple solution unfortunately has a problem - it is blinking and twitching (I don't know how to call it right) when scrolls slowly. So instead setTranslationY() I've used an objectAnimator:
public void resizePagerContainer(AbsListView absListView){
.............
ObjectAnimator moveAnim = ObjectAnimator.ofFloat(llVendorDescriptionPagerContainer, "translationY", translationY);
moveAnim.start();
..............
}
I don't like this solution because 1) anyway it does resize viewpager with delay, not instantly 2) I don't think that is good idea to create many ObjectAnimator's objects every time when I scroll my listView.
Need your help and fresh ideas. Regards.
I'm assuming that you are scrolling the top header (the ImageView is a child of the header) based on the scrollY of the ListView/ScrollView, as shown below:
float translationY = Math.max(-scrollY, mMinHeaderTranslation);
mHeader.setTranslationY(translationY);
mTopImage.setTranslationY(-translationY / 3); // For parallax effect
If you want to stick the header/image to a certain dimension and continue the scrolling without moving it anymore, then you can change the value of mMinHeaderTranslation to achieve that effect.
//change this value to increase the dimension of header stuck on the top
int tabHeight = getResources().getDimensionPixelSize(R.dimen.tab_height);
mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
mMinHeaderTranslation = -mHeaderHeight + tabHeight;
The code snippets above are in reference to my demo but I think it's still general enough for you.
If you're interested you can check out my demo
https://github.com/boxme/ParallaxHeaderViewPager
Have you tried CoordinatorLayout from this new android's design support library? It looks like it's what you need. Check this video from 3:40 or this blog post.

Android ViewPager different transitions for different pages

Is it possible to setup different PageTransformers for different fragments in ViewPager?
I would like to use ZoomOutPageTransformer when the user swipes between (0, 1) and (n-1, n) fragments of ViewPager with n fragments and use the default transitions for all other cases.
What I tried:
Detect the current page with mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { ... }) and apply different transitions here. But, for example, if the user is on the first page - how to set ZoomOutPageTransformer only for the case when he will swipe to the left (0 page) and do it before animation is started?
I had a less similar requirement wherein I had applied Depth page transformer to all my pages by default and on tap of a button I changed it to Vertical page transformer and then back to Depth page. (A lil wierd but thats how it was)
I did the below:
Applied viewPager.setPageTransformer(true, new DepthPageTransformer()); for all the pages.
onClick I changed it to viewPager.setPageTransformer(true, new VerticalPageTransformer());. Now here's the catch in-order for this to function smoothly I had to use a handler in order to change the page a little later to ensure VerticalPager takes effect. I achieved this by calling viewPager.setCurrentPosition(viewPager.getCurrentItem() + 1)
After this inside onPageChangeListener's onPageSelected method I changed it back to viewPager.setPageTransformer(true, new DepthPageTransformer()); again inside a handler to ensure it's done after my vertical animation is completed.
Note - I had also accessed ViewPager's scroller to achieve the above to define my own speed for the page change.
Let me know if this makes sense, since you need it to be done based on page numbers. If it does I will share my code. :)
This is quite old, but wish it's not too late for somebody
Step 1:
Create custom ViewPager which extends from ViewPager.
Step 2:
Determine which Fragment positions (ViewPager page integers) you need to have a unique PageTransformer for them. Then add these indices into a list within the custom ViewPager.
Step 3:
Override onPageScrolled(int position, float offset, int offsetPixels):
Check if the position is in your list of indices, if so, then you have to create a Custom PageTransformer object; and then utilize the ViewPager setPageTransformer() to change the page transformation.
For positions other than that, then you've to set the default PageTransformer (or you can also you another custom PageTransformer object if you wish.
Code
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context context) {
super(context);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
PageTransformer mDepthPageTransformer = new PageTransformer() {
private static final float MIN_SCALE = 0.75f;
public void transformPage(#NonNull View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1f);
view.setTranslationX(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
};
PageTransformer mDefaultPageTransformer = new PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
}
};
#Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
List<Integer> pos = new ArrayList<>();
pos.add(0);
pos.add(n - 1); // n is the no. of pages as in the question
if (pos.contains(position)) {
this.setPageTransformer(true, mDepthPageTransformer);
} else {
this.setPageTransformer(true, mDefaultPageTransformer);
}
super.onPageScrolled(position, offset, offsetPixels);
}
}
Documentation
Slide between fragments using ViewPager
setPageTransformer() method
Note: mDepthPageTransformer used in my example is taken from the above mentioned documentation.
Inspite Of using mViewPager.setOnPageChangeListener , a single PageTransformer with different animations can help.
Have a look at first paragraph here ,
http://developer.android.com/training/animation/screen-slide.html#pagetransformer

How change ActionBar colour when swiping between fragments (Material Design)?

I have an app i am doing, which has a FragmentPagerAdapter setup with 3 fragments to swipe between on the main page.
I have been trying to get it setup so as you swipe between fragments, the action bar changes color (fades in and out).
However i am not sure how i should do this.
What method is called when you swipe between fragments? I.E where should i put the code to change the action bar colour?
And also how would i get the fade in and out effect (so it fades out one colour into another one)?
I would really appreciate anyones help.
Thanks in advance
Cheers
Corey :)
What method is called when you swipe between fragments?
You're looking for ViewPager.OnPageChangeListener.onPageScrolled. This will give you:
position Position index of the first page currently being displayed.
positionOffset Value from [0, 1) indicating the offset from the page at position.
positionOffsetPixels Value in pixels indicating the offset from position.
Although, you'll only need the first two parameters. What you'll want to do is bind a particular color to each of your fragments, retrieve both the current page and next page colors, then blend them together using the positionOffset ratio to create your new ActionBar background.
A useful algorithm for blending two colors based on a ratio can be found in Google's new SlidingTabStrip example. 0.0 will return the second color, 0.5 will return an even blend, and 1.0 will return the first color
static int blendColors(int from, int to, float ratio) {
final float inverseRation = 1f - ratio;
final float r = Color.red(from) * ratio + Color.red(to) * inverseRation;
final float g = Color.green(from) * ratio + Color.green(to) * inverseRation;
final float b = Color.blue(from) * ratio + Color.blue(to) * inverseRation;
return Color.rgb((int) r, (int) g, (int) b);
}
Here's a simple example:
ColorFragment
public class ColorFragment extends Fragment {
private static final String KEY_COLOR = "colorfragment:color";
/** Empty constructor as per the {#link Fragment} docs */
public ColorFragment() {
}
public static ColorFragment newInstance(int color) {
final Bundle args = new Bundle();
args.putInt(KEY_COLOR, color);
final ColorFragment fragment = new ColorFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final FrameLayout rootView = new FrameLayout(getActivity());
rootView.setBackgroundColor(getArguments().getInt(KEY_COLOR));
return rootView;
}
public int getColor() {
return getArguments().getInt(KEY_COLOR);
}
}
Pulling it all together
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the ActionBar background
final ColorDrawable actionBarBackground = new ColorDrawable();
getSupportActionBar().setBackgroundDrawable(actionBarBackground);
...
final PagerAdapter pagerAdapter = ...;
...
// Bind your data to your PagerAdapter
...
final ViewPager pager = ...;
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (position >= pagerAdapter.getCount() - 1) {
// Guard against ArrayIndexOutOfBoundsException
return;
}
// Retrieve the current and next ColorFragment
final ColorFragment from = (ColorFragment) pagerAdapter.getItem(position);
final ColorFragment to = (ColorFragment) pagerAdapter.getItem(position + 1);
// Blend the colors and adjust the ActionBar
final int blended = blendColors(to.getColor(), from.getColor(), positionOffset);
actionBarBackground.setColor(blended);
}
});
pager.setAdapter(pagerAdapter);
}
Results
http://gfycat.com/CautiousBewitchedJabiru
I hope that helps you out some!
You could make your FragmentPagerAdapter implements ViewPager.OnPageChangeListener.
Then, override onPageSelected
#Override
public void onPageSelected(int position) {
// get the action bar here and change color
}
As for the color change animation. I didn't try it, but this is from another stackoverflow issue :
Android objectAnimator animate backgroundColor of Layout

Categories

Resources