从屏幕底部向上滑动布局

我有一个隐藏的布局。点击一个按钮,我希望它从底部向上滑动,将整个屏幕内容向上推,非常类似于 whatsapp 在聊天屏幕中显示表情符号面板的方式。

我看过“滑动抽屉”这招对我不管用。它需要一个图像作为手柄,显示在屏幕的中心,我不想这样。它也幻灯片在现有的屏幕内容,我正在寻找一种方式来移动现有的内容向上。

更新1:

我试着使用 Sanket Kachhela 建议的动画。但是隐藏的布局从来没有显示出来。这是密码。

布局(activity _ main.xml) :

<RelativeLayout
android:id="@+id/main_screen"
android:layout_width="match_parent"
android:layout_height="match_parent" >


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:layout_alignParentTop="true"/>


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:layout_centerInParent="true"/>


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Slide up / down"
android:layout_alignParentBottom="true"
android:onClick="slideUpDown"/>


</RelativeLayout>


<RelativeLayout
android:id="@+id/hidden_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/main_screen">


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name" />


</RelativeLayout>

活动(MainActivity.java) :

package com.example.slideuplayout;


import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;


public class MainActivity extends Activity {


private ViewGroup hiddenPanel;
private boolean isPanelShown;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


hiddenPanel = (ViewGroup)findViewById(R.id.hidden_panel);
hiddenPanel.setVisibility(View.INVISIBLE);
isPanelShown = false;
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


public void slideUpDown(final View view) {
if(!isPanelShown) {
// Show the panel
Animation bottomUp = AnimationUtils.loadAnimation(this,
R.anim.bottom_up);


hiddenPanel.startAnimation(bottomUp);
hiddenPanel.setVisibility(View.VISIBLE);
isPanelShown = true;
}
else {
// Hide the Panel
Animation bottomDown = AnimationUtils.loadAnimation(this,
R.anim.bottom_down);


hiddenPanel.startAnimation(bottomDown);
hiddenPanel.setVisibility(View.INVISIBLE);
isPanelShown = false;
}
}


}

动画:

Bottom _ up. xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="75%p"
android:toYDelta="0%p"
android:fillAfter="true"
android:duration="500" />
</set>

Bottom _ down. xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0%p"
android:toYDelta="100%p"
android:fillAfter="true"
android:interpolator="@android:anim/linear_interpolator"
android:duration="500" />
</set>

有什么办法吗?

谢谢。

204831 次浏览

Use these animations:

bottom_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="75%p" android:toYDelta="0%p"
android:fillAfter="true"
android:duration="500"/>
</set>

bottom_down.xml

 <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">


<translate android:fromYDelta="0%p" android:toYDelta="100%p" android:fillAfter="true"
android:interpolator="@android:anim/linear_interpolator"
android:duration="500" />


</set>

Use this code in your activity for hiding/animating your view:

Animation bottomUp = AnimationUtils.loadAnimation(getContext(),
R.anim.bottom_up);
ViewGroup hiddenPanel = (ViewGroup)findViewById(R.id.hidden_panel);
hiddenPanel.startAnimation(bottomUp);
hiddenPanel.setVisibility(View.VISIBLE);

Use this layout. If you want to animate the main view shrinking you'll need to add animation to the height of the hidden bar, buy it may be good enough to use the translate animation on the bar, and have the main view height jump instead of animate.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >


<RelativeLayout
android:id="@+id/main_screen"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="@string/hello_world" />


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/hello_world" />


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="slideUpDown"
android:text="Slide up / down" />
</RelativeLayout>


<RelativeLayout
android:id="@+id/hidden_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#fcc"
android:visibility="visible" >


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name" />
</RelativeLayout>


</LinearLayout>

Ok, there are two possible approaches. The simplest - is to use a sliding menu library. It allows creating a bottom sliding menu, it can animate the top container to make bottom visible, it suports both dragging it with your finger, or animating it programmatically via button (StaticDrawer).

Harder way - if you want to use Animations, as was already suggested. With animations you must FIRST change your layouts. So try first to make your layout change to the final state without any animations whatsoever. Because it is very likely that you are not laying out your views properly in RelativeLayout, so even though you show your bottom view, it remains obscured by the top one. Once you achieved proper layout change - all you need to do is to is to remember translations before layout and apply translate animation AFTER layout.

You were close. The key is to have the hidden layout inflate to match_parent in both height and weight. Simply start it off as View.GONE. This way, using the percentage in the animators works properly.

Layout (activity_main.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_screen"
android:layout_width="match_parent"
android:layout_height="match_parent" >


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="@string/hello_world" />


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/hello_world" />


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="slideUpDown"
android:text="Slide up / down" />


<RelativeLayout
android:id="@+id/hidden_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:visibility="gone" >


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:layout_centerInParent="true"
android:onClick="slideUpDown" />
</RelativeLayout>


</RelativeLayout>

Activity (MainActivity.java):

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;


public class OffscreenActivity extends Activity {
private View hiddenPanel;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);


hiddenPanel = findViewById(R.id.hidden_panel);
}


public void slideUpDown(final View view) {
if (!isPanelShown()) {
// Show the panel
Animation bottomUp = AnimationUtils.loadAnimation(this,
R.anim.bottom_up);


hiddenPanel.startAnimation(bottomUp);
hiddenPanel.setVisibility(View.VISIBLE);
}
else {
// Hide the Panel
Animation bottomDown = AnimationUtils.loadAnimation(this,
R.anim.bottom_down);


hiddenPanel.startAnimation(bottomDown);
hiddenPanel.setVisibility(View.GONE);
}
}


private boolean isPanelShown() {
return hiddenPanel.getVisibility() == View.VISIBLE;
}


}

Only other thing I changed was in bottom_up.xml. Instead of

android:fromYDelta="75%p"

I used:

android:fromYDelta="100%p"

But that's a matter of preference, I suppose.

You could define the mainscreen and the other screen that you want to scroll up as fragments. When the button on the mainscreen is pushed, the fragment would send a message to the activity which would then replace the mainscreen with the one that you want to scroll up and animate the replacement.

Here is what worked in the end for me.

Layouts:

activity_main.xml

<RelativeLayout
android:id="@+id/main_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true">


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:layout_alignParentTop="true"/>


<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:layout_centerInParent="true" />


<Button
android:id="@+id/slideButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Slide up / down"
android:layout_alignParentBottom="true"
android:onClick="slideUpDown"/>


</RelativeLayout>

hidden_panel.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/hidden_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test" />
</LinearLayout>

Java: package com.example.slideuplayout;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;


public class MainActivity extends Activity {


private ViewGroup hiddenPanel;
private ViewGroup mainScreen;
private boolean isPanelShown;
private ViewGroup root;


int screenHeight = 0;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


mainScreen = (ViewGroup)findViewById(R.id.main_screen);
ViewTreeObserver vto = mainScreen.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
screenHeight = mainScreen.getHeight();
mainScreen.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});


root = (ViewGroup)findViewById(R.id.root);


hiddenPanel = (ViewGroup)getLayoutInflater().inflate(R.layout.hidden_panel, root, false);
hiddenPanel.setVisibility(View.INVISIBLE);


root.addView(hiddenPanel);


isPanelShown = false;
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


public void slideUpDown(final View view) {
if(!isPanelShown) {
// Show the panel
mainScreen.layout(mainScreen.getLeft(),
mainScreen.getTop() - (screenHeight * 25/100),
mainScreen.getRight(),
mainScreen.getBottom() - (screenHeight * 25/100));






hiddenPanel.layout(mainScreen.getLeft(), mainScreen.getBottom(), mainScreen.getRight(), screenHeight);
hiddenPanel.setVisibility(View.VISIBLE);


Animation bottomUp = AnimationUtils.loadAnimation(this,
R.anim.bottom_up);


hiddenPanel.startAnimation(bottomUp);


isPanelShown = true;
}
else {
isPanelShown = false;


// Hide the Panel
Animation bottomDown = AnimationUtils.loadAnimation(this,
R.anim.bottom_down);
bottomDown.setAnimationListener(new AnimationListener() {


@Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub


}


@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub


}


@Override
public void onAnimationEnd(Animation arg0) {
isPanelShown = false;


mainScreen.layout(mainScreen.getLeft(),
mainScreen.getTop() + (screenHeight * 25/100),
mainScreen.getRight(),
mainScreen.getBottom() + (screenHeight * 25/100));


hiddenPanel.layout(mainScreen.getLeft(), mainScreen.getBottom(), mainScreen.getRight(), screenHeight);
}
});
hiddenPanel.startAnimation(bottomDown);
}
}
}

You just need to add some line in your app, please find it from below link:

Show and hide a View with a slide up/down animation

Just add an animation to your layout like this:

mLayoutTab.animate()
.translationYBy(120)
.translationY(0)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));

My code to make animation slide up, slide down without XML

private static ObjectAnimator createBottomUpAnimation(View view,
AnimatorListenerAdapter listener, float distance) {
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", -distance);
//        animator.setDuration(???)
animator.removeAllListeners();
if (listener != null) {
animator.addListener(listener);
}
return animator;
}


public static ObjectAnimator createTopDownAnimation(View view, AnimatorListenerAdapter listener,
float distance) {
view.setTranslationY(-distance);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", 0);
animator.removeAllListeners();
if (listener != null) {
animator.addListener(listener);
}
return animator;
}

Using For slide down

createTopDownAnimation(myYellowView, null, myYellowView.getHeight()).start();

For slide up

createBottomUpAnimation(myYellowView, null, myYellowView.getHeight()).start();

enter image description here

Try this below code, Its very short and simple.

transalate_anim.xml

<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2013 The Android Open Source Project


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at


http://www.apache.org/licenses/LICENSE-2.0


Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="4000"
android:fromXDelta="0"
android:fromYDelta="0"
android:repeatCount="infinite"
android:toXDelta="0"
android:toYDelta="-90%p" />


<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fromAlpha="0.0"
android:repeatCount="infinite"
android:toAlpha="1.0" />
</set>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="match_parent"
tools:context="com.naveen.congratulations.MainActivity">




<ImageView
android:id="@+id/image_1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:srcCompat="@drawable/balloons" />
</android.support.constraint.ConstraintLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView imageView1 = (ImageView) findViewById(R.id.image_1);
imageView1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startBottomToTopAnimation(imageView1);
}
});


}


private void startBottomToTopAnimation(View view) {
view.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate_anim));
}
}

bottom_up_navigation of image

Here is a solution as an extension of [https://stackoverflow.com/a/46644736/10249774]

Bottom panel is pushing main content upwards

https://imgur.com/a/6nxewE0

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/my_button"
android:layout_marginTop="10dp"
android:onClick="onSlideViewButtonClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="main "
android:textSize="70dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="main "
android:textSize="70dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="main "
android:textSize="70dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="main"
android:textSize="70dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="main"
android:textSize="70dp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/footer_view"
android:background="#a6e1aa"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="footer content"
android:textSize="40dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="footer content"
android:textSize="40dp" />
</LinearLayout>
</RelativeLayout>

MainActivity:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {
private Button myButton;
private View footerView;
private View mainView;
private boolean isUp;
private int anim_duration = 700;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


footerView = findViewById(R.id.footer_view);
mainView = findViewById(R.id.main_view);
myButton = findViewById(R.id.my_button);


// initialize as invisible (could also do in xml)
footerView.setVisibility(View.INVISIBLE);
myButton.setText("Slide up");
isUp = false;
}
public void slideUp(View mainView , View footer_view){
footer_view.setVisibility(View.VISIBLE);
TranslateAnimation animate_footer = new TranslateAnimation(
0,                 // fromXDelta
0,                 // toXDelta
footer_view.getHeight(),  // fromYDelta
0);                // toYDelta
animate_footer.setDuration(anim_duration);
animate_footer.setFillAfter(true);
footer_view.startAnimation(animate_footer);


mainView.setVisibility(View.VISIBLE);
TranslateAnimation animate_main = new TranslateAnimation(
0,                 // fromXDelta
0,                 // toXDelta
0,  // fromYDelta
(0-footer_view.getHeight()));                // toYDelta
animate_main.setDuration(anim_duration);
animate_main.setFillAfter(true);
mainView.startAnimation(animate_main);
}
public void slideDown(View mainView , View footer_view){
TranslateAnimation animate_footer = new TranslateAnimation(
0,                 // fromXDelta
0,                 // toXDelta
0,                 // fromYDelta
footer_view.getHeight()); // toYDelta
animate_footer.setDuration(anim_duration);
animate_footer.setFillAfter(true);
footer_view.startAnimation(animate_footer);




TranslateAnimation animate_main = new TranslateAnimation(
0,                 // fromXDelta
0,                 // toXDelta
(0-footer_view.getHeight()),  // fromYDelta
0);                // toYDelta
animate_main.setDuration(anim_duration);
animate_main.setFillAfter(true);
mainView.startAnimation(animate_main);
}


public void onSlideViewButtonClick(View view) {
if (isUp) {
slideDown(mainView , footerView);
myButton.setText("Slide up");
} else {
slideUp(mainView , footerView);
myButton.setText("Slide down");
}
isUp = !isUp;
}
}