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.
Related
I have searched for a possible solution to imitating the collapsible toolbar but I can't seem to start it with my current knowledge on handling complex layouts.
From the layout above, I have a docked layout above, an imageview, 2 textviews. What I want to do is when I scroll up, the imageview will transfer its self at the top right, the textview without border will be pushed at the top, and the last textview should disappear.
Just like this.
As of now, I was able to move the ImageView to the required position when scrolling with this code:
private void scaleImage(float x, float y) {
movingView.setScaleX(x);
movingView.setScaleY(y);
movingView.setPivotX(1.3f * movingView.getWidth());
movingView.setPivotY(1.5f * movingView.getHeight());
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
float offsetFactorDown = (float) (getScrollY()) / (float) scrollRange;
float scaleFactor = 1F - offsetFactorDown * 0.9F;
scaleImage(scaleFactor, scaleFactor);
}
The getScrollY() is not consistent which only gives me the right position when I am scrolling slowly. What else can I use to be the basis for the offset which is consistent?
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.
I have an horizontal recycler view snapping to center position. I want to set a bottom margin to centered items gradually. It's like os x dock grow effect, but i don't want to scale up, i want to push up.
I've done it with animations but it's not a good result and they are fired on recycler view scroll state changes.
Someone can indicate a solution to me?
Thanks in advance
After a lot of time I'm here to share my solution, more simple than I believed. I have extended RecyclerView and overriden onDraw method to set margin to RecyclerView's children based on their distance from center. It's not much clear, but now I have no time to make it better, and if someone need it, he can take a look to take inspiration
#Override
public void onDraw(Canvas c) {
super.onDraw(c);
int size = getChildCount();
for (int i = 0; i < size; i++) {
View v = getChildAt(i);
int x = DisplayHelper.pxToDp(act, (int) v.getX());
topMargin = x - startXCenter;
if (topMargin < -100 || topMargin > 100) {
topMargin = MAX_MARGIN;
} else if (topMargin < 0) {
topMargin *= -1;
}
topMargin = topMargin - MAX_MARGIN;
if (null != v) {
v.setY(topMargin);
}
}
}
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.
I'm using a cover flow in my Android App with this tutorial link http://www.inter-fuser.com/2010/01/android-coverflow-widget.html and I already use it well. But my problem is when the Android version is 4.1 the cover flow semms not working well, because the images is not being centered or aligning well after choosing an image. But if the Android version is below 4.0 it works well like in the video of the link.
Did anyone have a thoughts regards this issue?
UPDATE
A fix for this issue is to make the following change to getChildStaticTransformation(View child, Transformation t)
protected boolean getChildStaticTransformation(View child, Transformation t) {
child.invalidate(); // add this line
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth();
int rotationAngle = 0;
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
if (childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
: mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return true;
}
--
I had this same problem recently. This has to do with the Gallery having been deprecated. As an alternative, I implemented something similar to this using a HorizontalScrollView and centering using .scrollTo(). The problem with this solution is that scrollTo() aligns with the left side of the View and so you have to compute the middle y0urself. If the layout fills the screen you're going to have to apply padding to the left and right side of the view to force the selected element to the center.
A word of caution. Horizontal scroll views don't have animatible scrolling so it's going to be a snap-to behavior. You can get around this by scrolling using a timer but it's not a terribly elegant solution.