`

在界面顶部滑动展开的自定义FrameLayout

阅读更多


用法:
translationView.show();
translationView.hide();
translationView.setShadowColor(ActivityCompat.getColor(MainActivity.this, R.color.blue));//设置背景颜色


源码:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.ColorInt;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

public class TranslationView extends FrameLayout {

    private static final String TAG = "TranslationView";
    private static final int DEFAULT_COLOR = 0x50000000;
    private int mShadowColor = DEFAULT_COLOR;
    private boolean mIsShow = false;

    private View mTranslationView;


    public TranslationView(Context context) {
        super(context, null);
    }

    public TranslationView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public TranslationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onFinishInflate() {
        if (getChildCount() != 2) {
            throw new IllegalStateException("only and should contain two child view");
        }
        mTranslationView = getChildAt(1);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG, "onMeasure");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mTranslationView.layout(0, -mTranslationView.getHeight(), mTranslationView.getWidth(), 0);
    }


    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        if (mIsShow && child == mTranslationView) {
            canvas.drawColor(mShadowColor);
        }
        return super.drawChild(canvas, child, drawingTime);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        switch (action){
            case MotionEvent.ACTION_DOWN:{
                if(mIsShow&&inShadow(ev)){
                    hide();
                    return true;
                }
            }
        }
        return  super.onInterceptTouchEvent(ev);
    }

    private boolean inShadow(MotionEvent ev) {
        float x = ev.getX();
        float y = ev.getY();
        final float leftEdge = mTranslationView.getX();
        final float rightEdge = leftEdge+mTranslationView.getWidth();
        final float topEdge =mTranslationView.getHeight();
        final float bottomEdge = getHeight()+topEdge;
        return x > leftEdge && x < rightEdge && y > topEdge && y < bottomEdge;
    }


    public void show() {
        if (!mIsShow) {
            mIsShow = true;
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTranslationView, "translationY", mTranslationView.getTranslationY(), mTranslationView.getHeight());
            objectAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    invalidate();
                }
            });
            objectAnimator.start();
        }
    }

    public void hide() {
        if (mIsShow) {
            mIsShow = false;
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTranslationView, "translationY", mTranslationView.getTranslationY(), -mTranslationView.getHeight());
            objectAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    invalidate();
                }
            });
            objectAnimator.start();
        }
    }

    public void setShadowColor(@ColorInt int color) {
        mShadowColor = color;
    }
}
  • 大小: 178.8 KB
分享到:
评论

相关推荐

    Android顶部滑动菜单

    在Android开发中,创建一个类似今日头条顶部滑动菜单的效果,是一种常见的用户界面设计,它可以提供良好的用户体验,方便用户浏览和切换不同的内容板块。这个菜单通常被称为TabLayout或SlideMenu,它是一个滑动的...

    android可滑动的顶部条

    2. **创建顶部滑动条布局**:在XML布局文件中设计顶部条,可以包含多个Tab标签,每个标签代表一个页面。可以使用`TabHost`,`TabWidget`和`FrameLayout`等组件来构建。 3. **设置Tab监听器**:为每个Tab设置点击...

    网易顶部可左右滑动分类

    在Android应用开发中,"网易顶部可左右滑动分类"是一种常见的交互设计,它使得用户在浏览内容时能轻松切换不同的分类。这种效果通常应用于新闻、电商等应用的首页,以展示不同主题或类别的信息。本文将详细介绍如何...

    Android 仿百度手机助手首页滑动效果 demo代码

    总的来说,通过学习和实践这个demo,开发者可以了解到如何在Android中实现自定义视图的滑动效果,以及如何通过手势事件处理和视图动画来提升用户体验。这对于构建具有沉浸式体验的Android应用来说是非常有价值的技能...

    自定义Android中TabHost组件显示在屏幕底部,并实现滑动切换页面(源码下载)

    在Android应用开发中,TabHost组件是一个非常常用的工具,它用于创建带有标签页的应用界面,让用户可以在多个视图间切换。本教程将详细介绍如何自定义TabHost组件使其显示在屏幕底部,并实现通过滑动切换页面的功能...

    android ListView向上滑动隐藏标题,下拉显示标题栏,完美解决滑动出现的空白问题。

    然而,在实际应用中,我们经常遇到标题栏在用户滚动列表时的交互需求,比如标题随着ListView的滑动而隐藏或显示,以优化用户体验并提高界面的空间利用率。本教程将详细讲解如何实现这个功能,同时解决滑动过程中可能...

    Android-自定义滑动菜单(抽屉效果)

    在Android应用开发中,自定义滑动菜单,也被称为抽屉式导航(Drawer Navigation)或侧滑菜单,是一种常见的设计模式。它允许用户通过从屏幕边缘向内滑动来显示额外的功能选项或导航层次。这种设计在许多应用程序中都能...

    仿淘宝商品页上下滑动控件

    为了增强用户体验,还可以添加一些额外的功能,如回弹效果(OverScroll)、手势检测(GestureDetector)以支持快速滑动到顶部或底部,以及添加状态栏和导航栏的透明度变化效果,使整个界面看起来更连贯。 在实际...

    仿新浪微博下拉刷新继承FrameLayout.zip

    在安卓应用开发中,"仿新浪微博下拉刷新继承FrameLayout"是一个常见的功能需求,它涉及到Android UI组件的自定义和下拉刷新(Pull-to-Refresh)机制的实现。这个项目可能是一个毕业设计或课程设计任务,旨在提升...

    android 菜单滑动demo

    在Android开发中,菜单滑动效果是用户界面中常见的交互元素,可以提升应用的用户体验。本文将基于"android 菜单滑动demo"来详细探讨如何实现这一功能,同时结合提供的标签"源码"和"工具",我们将深入源码层面理解其...

    自定义Android中TabHost组件显示在屏幕底部 并实现滑动切换

    在标准布局中,TabHost通常显示在屏幕顶部,但为了满足特定设计需求,有时我们需要将其调整到屏幕底部并实现滑动切换。本教程将详细讲解如何自定义TabHost,使其位于屏幕底部,并实现平滑的页面切换效果,类似于米聊...

    自定义下拉刷新viewgroup

    这是一种常见的用户界面交互模式,用户可以通过在顶部滚动列表时向下拉动来触发数据的刷新。这种设计常见于新闻应用、社交媒体应用等,使得用户可以轻松获取最新内容。 在Android中,我们通常会使用...

    应用源码仿新浪微博下拉刷新继承FrameLayout.zip

    在这个项目中,下拉刷新功能被集成到FrameLayout中,意味着开发者可能自定义了FrameLayout的行为,使其在用户下拉时触发刷新操作。 2. **下拉刷新(Pull-to-Refresh)机制**: 这是移动应用中常见的功能,用户在顶部...

    SlidingMenu 左右滑动 按钮点击滑动

    在这个“LeftandRightSlidingmenu”项目中,你可能还会发现如何自定义菜单项、添加动画效果、处理滑动监听事件等。通过结合使用SlidingMenu库和按钮点击事件,你可以创建一个功能丰富的应用,让用户通过简单的手势和...

    android实现自定义tab页

    在Android应用开发中,创建自定义的Tab页可以极大地提升用户体验和界面的个性化。本教程将深入探讨如何利用RadioButton实现非源生风格的Tab页,而不是依赖于原生的TabHost或ViewPager。以下是对这个主题的详细讲解:...

    Android应用源码之QQTabDemo(高仿QQ2012滑动菜单).rar

    1. **布局设计**:项目使用了LinearLayout、RelativeLayout和FrameLayout等基本布局组件,通过组合和嵌套构建出复杂的界面结构。同时,为了实现滑动效果,可能还使用了SlidingDrawer或者Android的滑动库,如...

    基于Android的仿新浪微博下拉刷新继承FrameLayout.zip

    在Android开发中,"基于Android的仿新浪微博下拉刷新继承FrameLayout.zip" 是一个实践项目,旨在教授如何在Android应用中实现类似新浪微博的下拉刷新功能。这个项目的核心是通过自定义View组件来扩展Android的基础...

    qq5.0界面效果实现

    在Android应用开发中,QQ5.0界面效果的实现是一个重要的设计和功能升级,它引入了独特的滑动菜单(SlidingMenu)体验,为用户提供更流畅、直观的交互方式。这个效果是通过继承HorizontalScrollView来达成的,...

    android 界面效果

    Android还提供了许多高级组件,如滑动抽屉(DrawerLayout)、浮动动作按钮(FloatingActionButton)和工具栏(Toolbar),这些都极大地丰富了界面设计的可能性。 在Android中实现界面效果,动画(Animation)也起着...

Global site tag (gtag.js) - Google Analytics