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.
Related
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);
}
How do I scale up/enlarge RecyclerView items only when they are the most centered and shrink them when user swipes away?
I was able to achieve that with a ViewPager like so:
viewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(View page, float position) {
final float normalizedPosition = Math.abs(Math.abs(position) - 1);
page.setScaleX(normalizedPosition / 2 + 0.7f);
page.setScaleY(normalizedPosition / 2 + 0.7f);
page.setPadding(-dpToPx(40), 0, -dpToPx(40), 0);
}
});
But I had to rewrite the functionality and now I am using a horizontal recycler view.
I was able to set a scroll listener to the RecyclerView and scale up the current view, but I don't know how to scale it down when it goes out of focus
It seems like a challenging animation, but I have a feeling this can be done very easily. I am trying to achieve an animation between Fragments like below (see 2nd and 3rd quadrant)
Enter and exit are not difficult, but pre-displaying next and previous card's screen and seamless transition to next card is out of my knowledge scope. Please, if anyone has worked on a similar animation, give me some pointers.
EDIT
The official documentation of Android transitions on click i.e. when user clicks page is zoomed out to show last and previous page and swipe moves it to next one. My requirement is to leave the page at zoomed out level and transition on button clicks:
Question: How will be the view default out to x zoom level to show previous next page parts and transition on click.
You can customize the transition animation between fragments using PageTransformer.
ZoomOutPageTransformer
import android.support.v4.view.ViewPager;
import android.view.View;
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
Usage
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
Official documentation.
Checkout this and this for showing boundaries of near one.
For folks who come to this question looking for similar requirement:
As Anoop suggests, official documentation is great. Simply implement viewPager.PagerTransform and supply the class to your viewPager. Also, transformPage (the implemented function) is very important in animation transition.
Next part, was to show corners of next and previous fragments. This can be acheived through xml of fragments. Reference : Android tip viewpager with protruding children
Hopes this helps someone to create interactive apps.
UPDATE
This post shared by Anoop makes this transformation a breeze. cheers!
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.
I am working on an app and I have something similar to the Hangouts app where there is the sliding tabs under the ToolBar but I wanted to integrate it into the ToolBar instead of existing in the Activity/Fragment layout.
I have tried increasing the height of the ToolBar and setting a custom view, but if I do that, the custom view is in the middle of the ToolBar and not underneath the Title and Menu Overflow Button.
I have tried several things. Latest is:
toolBar.setCustomView(customView, layoutParams);
Any help would be great.
EDIT: Should have been more clear...
I want the tabs like this to be in the ToolBar not in the Fragment Layout like this,
https://developer.android.com/samples/SlidingTabsColors/res/layout/fragment_sample.html
You will have to use the OnScrollChanged function in your ScrollView. ActionBar doesn't let you set the opacity , so set a background drawable on the actionbar and you can change its opacity based on the amount of scroll in the scrollview. I have given an example workflow
The function sets gives the appropriate alpha for the view locationImage based on its position WRT window .
this.getScrollY() gives you how much the scrollView has scrolled
public void OnScrollChanged(int l, int t, int oldl, int oldt) {
// Code ...
locationImage.setAlpha(getAlphaForView(locationImageInitialLocation- this.getScrollY()));
}
private float getAlphaForView(int position) {
int diff = 0;
float minAlpha = 0.4f, maxAlpha = 1.f;
float alpha = minAlpha; // min alpha
if (position > screenHeight)
alpha = minAlpha;
else if (position + locationImageHeight < screenHeight)
alpha = maxAlpha;
else {
diff = screenHeight - position;
alpha += ((diff * 1f) / locationImageHeight)* (maxAlpha - minAlpha); // 1f and 0.4f are maximum and min
// alpha
// this will return a number betn 0f and 0.6f
}
// System.out.println(alpha+" "+screenHeight +" "+locationImageInitialLocation+" "+position+" "+diff);
return alpha;
}
An example working sample at https://github.com/ramanadv/fadingActionBar , you can have a look at it.