Does someone know about Android animations? I want to create something like following:
I have a big image in the center of my device screen;
this image becomes small (by animation) and goes to the corner of my device screen;
Its something like in this bellow sequence:
Any hints would be very appreciated! Thanks in advance!
Use ViewPropertyAnimator, with methods like scaleXBy() and translateYBy(). You get a ViewPropertyAnimator by calling animate() on a View, on API Level 11+. If you are supporting older devices, NineOldAndroids offers a near-workalike backport.
You might also wish to read:
http://android-developers.blogspot.com/2011/05/introducing-viewpropertyanimator.html
http://developer.android.com/guide/topics/graphics/prop-animation.html
I have a class with the simultaneous rotation and movement. It's costly but it works on all API versions.
public class ResizeMoveAnimation extends Animation {
View view;
int fromLeft;
int fromTop;
int fromRight;
int fromBottom;
int toLeft;
int toTop;
int toRight;
int toBottom;
public ResizeMoveAnimation(View v, int toLeft, int toTop, int toRight, int toBottom) {
this.view = v;
this.toLeft = toLeft;
this.toTop = toTop;
this.toRight = toRight;
this.toBottom = toBottom;
fromLeft = v.getLeft();
fromTop = v.getTop();
fromRight = v.getRight();
fromBottom = v.getBottom();
setDuration(500);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float left = fromLeft + (toLeft - fromLeft) * interpolatedTime;
float top = fromTop + (toTop - fromTop) * interpolatedTime;
float right = fromRight + (toRight - fromRight) * interpolatedTime;
float bottom = fromBottom + (toBottom - fromBottom) * interpolatedTime;
RelativeLayout.LayoutParams p = (LayoutParams) view.getLayoutParams();
p.leftMargin = (int) left;
p.topMargin = (int) top;
p.width = (int) ((right - left) + 1);
p.height = (int) ((bottom - top) + 1);
view.requestLayout();
}
}
Related
I know how to use CircularReveal to reveal a view, so I'm looking for a way to do something like "CircularHide". In other words, I want to invisible a view by a circular animation (increasing radius) after making it visible. How can I do that?
I've written this to reveal:
private void startCircularReveal() {
RelativeLayout changeableLayout = findViewById(R.id.layoutChangeable);
int centerX = (likeButton.getRight() + likeButton.getLeft()) / 2;
int centerY = (likeButton.getBottom() + likeButton.getTop()) / 2;
float endRadius = (float) Math.hypot(changeableLayout.getWidth(), changeableLayout.getHeight());
changeableLayout.setVisibility(View.VISIBLE);
Animator revealAnimator = ViewAnimationUtils.createCircularReveal(changeableLayout,
centerX, centerY, 0, endRadius);
revealAnimator.setDuration(200).start();
}
I'm trying to create a select menu in Android instead of using Spinner, but i'm facing some problems with the layout. How can I create something like the image below using ListPopUpWindow?
Thanks
I really like these menus floating over selected items, so I created my own DropDown class which implements your case. It does pretty much what #uguboz wrote.
I'm using PopupWindow with a custom layout with a RecyclerView. Then I handle onClick, display that window and use overriden PopupWindow.update() to calculate correct window position.
The most interesting part would be this code:
public class DropDownMenu extends PopupWindow {
public boolean show(View anchor) {
mAnchorView = anchor;
super.showAtLocation(anchor, Gravity.START | Gravity.TOP, 0, 0);
update();
return true;
}
public void update() {
final Resources res = getContentView().getContext().getResources();
int margin = (int) res.getDimension(R.dimen.carbon_margin);
int itemHeight = (int) res.getDimension(R.dimen.carbon_listItemHeight);
int marginHalf = (int) res.getDimension(R.dimen.carbon_paddingHalf);
ArrayAdapter adapter = getAdapter();
Rect windowRect = new Rect();
mAnchorView.getWindowVisibleDisplayFrame(windowRect);
int hWindow = windowRect.bottom - windowRect.top;
int wWindow = windowRect.right - windowRect.left;
int[] location = new int[2];
mAnchorView.getLocationInWindow(location);
if (mode == DropDown.Mode.Over) {
int maxHeightAbove = location[1] - windowRect.top - marginHalf * 2;
int maxItemsAbove = maxHeightAbove / itemHeight;
int maxHeightBelow = hWindow - location[1] - marginHalf * 2;
int maxItemsBelow = maxHeightBelow / itemHeight;
int itemsBelow = Math.min(adapter.getItemCount() - selectedItem, maxItemsBelow);
int itemsAbove = Math.min(selectedItem, maxItemsAbove);
int popupX = location[0] - margin - marginHalf;
int popupY = location[1] - marginHalf * 2 - itemsAbove * itemHeight - (itemHeight - (mAnchorView.getHeight() - mAnchorView.getPaddingTop() -
mAnchorView.getPaddingBottom())) / 2 + mAnchorView.getPaddingTop();
int popupWidth = mAnchorView.getWidth() + margin * 2 + marginHalf * 2 - mAnchorView.getPaddingLeft() - mAnchorView.getPaddingRight();
int popupHeight = marginHalf * 4 + Math.max(1, itemsAbove + itemsBelow) * itemHeight;
popupWidth = Math.min(popupWidth, wWindow - marginHalf * 2);
popupX = Math.max(popupX, 0);
popupX = Math.min(popupX, wWindow - popupWidth);
LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
manager.scrollToPositionWithOffset(selectedItem - itemsAbove, 0);
update(popupX, popupY, popupWidth, popupHeight);
} else {
// not interesting
}
super.update();
}
}
The code is way too long to paste it here with all details, so I'll serve you a link to the class: DropDownMenu. Use it as you wish. I hope you'll find the code useful.
And I've made a sample for that image from the guidelines. It can be found in the sample app under Guidelines -> Menus/Behavior
My Android app has a game map with markers on it. When the user taps a marker, I'm displaying a PopupWindow aligned with the map marker (similar to Google Maps). The problem I'm having is if a marker is close to the top of the screen, the PopupWindow overlaps with the ActionBar (and under the status bar, if the marker is high enough).
I'm displaying the PopupWindow by calling showAtLocation(), which I'd hoped would constrain the view to inside the "Map" fragment (it does on the left and right sides), but that's not working.
I had already implemented an adjustment, to account for text inside the popup taking up more than one line, where I update the Y position of the popup after the View has been laid out. That worked with no problem, but when I tried to add another vertical adjustment for this situation, the PopupWindow's position does not change.
Here is the code for the PopupWindow implementation:
/**
* Displays a PopupWindow.
*/
public class MyPopupWindow extends PopupWindow
{
private Fragment m_fragment;
private int m_x;
private int m_y;
/**
* Displays a PopupWindow at a certain offset (x, y) from the center of fragment's view.
*/
public static MyPopupWindow createPopup (Context context, Fragment fragment, int x, int y)
{
// Create the PopupWindow's content view
LayoutInflater inflater = LayoutInflater.from (context);
View popupView = inflater.inflate (R.layout.view_map_popup, null);
MyPopupWindow popupWindow = new MyPopupWindow (popupView, x, y);
popupWindow.m_fragment = fragment;
popupWindow.showAtLocation (fragment.getView (), Gravity.CENTER, x, y);
return popupWindow;
}
private MyPopupWindow (View view, int x, int y)
{
super (view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
m_x = x;
m_y = y;
TextView title = (TextView) view.findViewById (R.id.lblMapPopupTitle);
title.setText ("Exercise Title");
TextView description = (TextView) view.findViewById (R.id.lblMapPopupDescription);
description.setText ("Exercise Description\nSecond Line\nThird Line\nFourth Line\nAnd one more...");
view.setVisibility (View.INVISIBLE);
view.addOnLayoutChangeListener (layoutChangeListener);
}
// If the tapped map location is too close to the edge, determine the
// delta-x and delta-y needed to align it with the PopupWindow
private int getHorizontalAdjustment (int popupWidth)
{
int horizontalAdjustment = 0;
int parentWidth = m_fragment.getView ().getWidth ();
if ((parentWidth / 2) + m_x + (popupWidth / 2) > parentWidth)
{
horizontalAdjustment = parentWidth - ((parentWidth / 2) + m_x + (popupWidth / 2));
}
else if ((parentWidth / 2) + m_x - (popupWidth / 2) < 0)
{
horizontalAdjustment = 0 - ((parentWidth / 2) + m_x - (popupWidth / 2));
}
return horizontalAdjustment;
}
private int getVerticalAdjustment (int popupHeight)
{
int verticalAdjustment = 0;
int parentHeight = m_fragment.getView ().getHeight ();
int y = m_y - (popupHeight / 2);
if ((parentHeight / 2) + y + (popupHeight / 2) > parentHeight)
{
verticalAdjustment = parentHeight - ((parentHeight / 2) + y + (popupHeight / 2));
}
else if ((parentHeight / 2) + y - (popupHeight / 2) < 20)
{
verticalAdjustment = 20 - ((parentHeight / 2) + y - (popupHeight / 2));
}
return verticalAdjustment;
}
private View.OnLayoutChangeListener layoutChangeListener = new View.OnLayoutChangeListener ()
{
#Override
public void onLayoutChange (View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
{
int height = bottom - top;
int width = right - left;
// Adjust the y-position for the inflated height of the view
// (so the popup's bottom edge lines up with the tapped marker's top edge)
int y = m_y - (height / 2);
int x = m_x;
// Determine any adjustments that need to be made to line up the tapped marker with the popup
int horizontalAdjustment = getHorizontalAdjustment (width);
int verticalAdjustment = getVerticalAdjustment (height);
y -= verticalAdjustment;
// Update our position with the re-calculated position
update (x, y, -1, -1);
view.setVisibility (View.VISIBLE);
}
};
}
The issue can be seen in this screenshot: PopupWindow overlaps ActionBar
Basically, I need to either (1) get the PopupWindow to clip to the Fragment's view and not overlap the ActionBar, or (2) get the PopupWindow to update its position in the event that it does overlap the ActionBar.
Any help is greatly appreciated.
I wants to swipe the ViewPager. I used following code for page swipe. But unfortunately is not working.
Solo solo = new Solo(getInstrumentation(), getActivity());
int screenHeight = activityUtils.getCurrentActivity().getWindowManager().getDefaultDisplay()
.getHeight();
int screenWidth = activityUtils.getCurrentActivity(false).getWindowManager().getDefaultDisplay()
.getWidth();
float x = screenWidth / 3.0f * 2.0f;
float y = screenHeight / 3.0f * 2.0f;
Try: 1
solo.swipe(x, 0, y, y, 40);
Try: 2
if (side == Side.LEFT)
drag(0, x, y, y, 40);
else if (side == Side.RIGHT)
drag(x, 0, y, y, 40);
Try: 3
Following method working but it's moving only single page and also it's moving very slowly.
solo1.scrollToSide(Solo.RIGHT);
Is there any option for fast swipe? Which one is best? Kindly share your ideas.
My code with Robotium 5.1
for (int count = 0; count < noOfPages; count++)
solo.swipeToRight(count);
Methods for view pager swipes
private void swipeToLeft(int stepCount) {
Display display = solo.getCurrentActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
float xStart = width - 10 ;
float xEnd = 10;
solo.drag(xStart, xEnd, height / 2, height / 2, stepCount);
}
private void swipeToRight(int stepCount) {
Display display = solo.getCurrentActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
float xStart = 10 ;
float xEnd = width - 10;
solo.drag(xStart, xEnd, height / 2, height / 2, stepCount);
}
solo.scrollToSide(Solo.RIGHT);
This implementation is also fast enough...
This issue has been fixed in Robotium 5.1. You can download it from here:
https://code.google.com/p/robotium/wiki/Downloads?tm=2
Well the code in the robotium repo for scroll to side is:
public void scrollToSide(int side) {
switch (side){
case RIGHT: scroller.scrollToSide(Scroller.Side.RIGHT, 0.70F); break;
case LEFT: scroller.scrollToSide(Scroller.Side.LEFT, 0.70F); break;
}
}
#SuppressWarnings("deprecation")
public void scrollToSide(Side side, float scrollPosition) {
int screenHeight = activityUtils.getCurrentActivity().getWindowManager().getDefaultDisplay()
.getHeight();
int screenWidth = activityUtils.getCurrentActivity(false).getWindowManager().getDefaultDisplay()
.getWidth();
float x = screenWidth * scrollPosition;
float y = screenHeight / 2.0f;
if (side == Side.LEFT)
drag(0, x, y, y, 40);
else if (side == Side.RIGHT)
drag(x, 0, y, y, 40);
}
public void drag(float fromX, float toX, float fromY, float toY,
int stepCount) {
dialogUtils.hideSoftKeyboard(null, false, true);
scroller.drag(fromX, toX, fromY, toY, stepCount);
}
So it looks like you must be close, my guess is the numbers you have used in your drag call are not able to make the view pager work. I would suggest trying th enumbers used by robotium EXCEPT for the last paramater which if you change should make the swipe happen quicker as this number is the ampount of events required to complete the swipe. You may need to experiment with the number.
i am trying to built the quick Action in my project. when i click the view it show the pop up window properly. But the arrow(arrow up, arrow down) which is point to the Parent View is not showing. i have tried it in many ways. if some one have the better solution or good logic please help me
thanks:
Here you can see the code:
public void show (View anchor) {
preShow();
int[] location = new int[2];
anchor.getLocationOnScreen(location);
Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
+ anchor.getHeight());
mRootView.setLayoutParams(new LayoutParams(300, 400));
mRootView.measure(200,300);
int rootWidth = mRootView.getMeasuredWidth();
int rootHeight = mRootView.getMeasuredHeight();
int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
int xPos = (screenWidth - rootWidth) / 2;
int yPos = anchorRect.top - rootHeight;
boolean onTop = true;
if (rootHeight > anchor.getTop()) {
yPos = anchorRect.bottom;
onTop = false;
}
if(onTop==true){
showArrow(R.id.arrow_down, anchorRect.centerX());
}
else
{
showArrow( R.id.arrow_up, anchorRect.centerX());
}
and showArrow method is as:
private void showArrow(int whichArrow, int requestedX) {
final View showArrow;
final View hideArrow;
if(whichArrow==R.id.arrow_down)
{
showArrow=mArrowDown;
hideArrow=mArrowUp;
}
else{
showArrow=mArrowUp;
hideArrow=mArrowDown;
}
final int arrowWidth = mArrowUp.getMeasuredWidth();
showArrow.setVisibility(View.VISIBLE);
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
param.leftMargin = requestedX - arrowWidth / 2;
hideArrow.setVisibility(View.INVISIBLE);
}
There is nothing wrong with you code.Probably,some thing will be wrong in your xml file. Please review you xml file. Try to modify you xml file. Hopefully,your problem will be resolved.