基本的类,只有一个:
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
public class SlideUp implements View.OnTouchListener, ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
private View view;
private float touchableTop;
private int autoSlideDuration = 300;
private SlideListener slideListener;
private ValueAnimator valueAnimator;
private float slideAnimationTo;
private float startPositionY;
private float viewStartPositionY;
private boolean canSlide = true;
private float density;
private float lowerPosition;
private float viewHeight;
private boolean hiddenInit;
public SlideUp(final View view) {
this.view = view;
this.density = view.getResources().getDisplayMetrics().density;
this.touchableTop = 300 * density;
view.setOnTouchListener(this);
view.setPivotY(0);
createAnimation();
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (hiddenInit)
{
viewHeight = view.getHeight();
hideImmediately();
}
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
}
public boolean isVisible(){
return view.getVisibility() == View.VISIBLE;
}
public void setSlideListener(SlideListener slideListener) {
this.slideListener = slideListener;
}
public void setAutoSlideDuration(int autoSlideDuration) {
this.autoSlideDuration = autoSlideDuration;
}
public float getAutoSlideDuration(){
return this.autoSlideDuration;
}
public void setTouchableTop(float touchableTop) {
this.touchableTop = touchableTop * density;
}
public float getTouchableTop() {
return this.touchableTop/density;
}
public boolean isAnimationRunning(){
return valueAnimator != null && valueAnimator.isRunning();
}
public void animateIn(){
this.slideAnimationTo = 0;
valueAnimator.setFloatValues(viewHeight, slideAnimationTo);
valueAnimator.start();
}
public void animateOut(){
this.slideAnimationTo = view.getHeight();
valueAnimator.setFloatValues(view.getTranslationY(), slideAnimationTo);
valueAnimator.start();
}
public void hideImmediately() {
if (view.getHeight() > 0)
{
view.setTranslationY(viewHeight);
view.setVisibility(View.GONE);
notifyVisibilityChanged(View.GONE);
}
else {
hiddenInit = true;
}
}
private void createAnimation(){
valueAnimator = ValueAnimator.ofFloat();
valueAnimator.setDuration(autoSlideDuration);
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(this);
valueAnimator.addListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
float touchedArea = event.getRawY() - view.getTop();
if (isAnimationRunning())
{
return false;
}
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
this.viewHeight = view.getHeight();
startPositionY = event.getRawY();
viewStartPositionY = view.getTranslationY();
if (touchableTop < touchedArea)
{
canSlide = false;
}
break;
case MotionEvent.ACTION_MOVE:
float difference = event.getRawY() - startPositionY;
float moveTo = viewStartPositionY + difference;
float percents = moveTo * 100 / view.getHeight();
if (moveTo > 0 && canSlide){
notifyPercentChanged(percents);
view.setTranslationY(moveTo);
}
if (event.getRawY() > lowerPosition)
{
lowerPosition = event.getRawY();
}
break;
case MotionEvent.ACTION_UP:
float slideAnimationFrom = view.getTranslationY();
boolean mustSlideUp = lowerPosition > event.getRawY();
boolean scrollableAreaConsumed = view.getTranslationY() > view.getHeight() / 5;
if (scrollableAreaConsumed && !mustSlideUp)
{
slideAnimationTo = view.getHeight();
}
else {
slideAnimationTo = 0;
}
valueAnimator.setFloatValues(slideAnimationFrom, slideAnimationTo);
valueAnimator.start();
canSlide = true;
lowerPosition = 0;
break;
}
return true;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = (float) animation.getAnimatedValue();
view.setTranslationY(val);
float percents = (view.getY() - view.getTop()) * 100 / viewHeight;
notifyPercentChanged(percents);
}
private void notifyPercentChanged(float percent){
if (slideListener != null)
{
slideListener.onSlide(percent);
}
}
private void notifyVisibilityChanged(int visibility){
if (slideListener != null)
{
slideListener.onVisibilityChanged(visibility);
}
}
@Override
public void onAnimationStart(Animator animator) {
view.setVisibility(View.VISIBLE);
notifyVisibilityChanged(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animator) {
if (slideAnimationTo > 0)
{
view.setVisibility(View.GONE);
notifyVisibilityChanged(View.GONE);
}
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
public interface SlideListener {
void onSlide(float percent);
void onVisibilityChanged(int visibility);
}
}
基本用法:
创建一个任意类型的布局
<LinearLayout
android:id="@+id/slideView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
获取这个view,SlideUp对象并传入view
View slideView = findViewById(R.id.slideView);
SlideUp slideUp = new SlideUp(slideView);
更复杂的例子:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import com.mancj.slideup.SlideUp;
public class SlideUpViewActivity extends AppCompatActivity {
private SlideUp slideUp;
private View dim;
private View slideView;
private FloatingActionButton fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slide_up_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
slideView = findViewById(R.id.slideView);
dim = findViewById(R.id.dim);
fab = (FloatingActionButton) findViewById(R.id.fab);
slideUp = new SlideUp(slideView);
slideUp.hideImmediately();
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
slideUp.animateIn();
fab.hide();
}
});
slideUp.setSlideListener(new SlideUp.SlideListener() {
@Override
public void onSlide(float percent) {
dim.setAlpha(1 - (percent / 100));
}
@Override
public void onVisibilityChanged(int visibility) {
if (visibility == View.GONE)
{
fab.show();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_slide_up_view, menu);
return true;
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:fitsSystemWindows="true"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<FrameLayout
android:alpha="0"
android:id="@+id/dim"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dimBg" />
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.slideup.SlideUpViewActivity">
<android.support.design.widget.AppBarLayout
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="0dp"
app:elevation="0dp"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_slide_up_view" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@drawable/ic_call_black_24dp"
app:fabSize="normal" />
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
- 大小: 8 MB
- main.zip (106.9 KB)
- 下载次数: 0
- 查看图片附件