类似微信下拉眼睛UI

public class EyeView extends FrameLayout {

    private Paint paint;
    private Bitmap bitmap;

    public EyeView(Context context) {
        super(context);
        init();
    }

    public EyeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public EyeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    @SuppressLint("NewApi")
    private void init() {
        setDrawingCacheEnabled(true);
        if (Build.VERSION.SDK_INT >= 11) {
            setLayerType(LAYER_TYPE_SOFTWARE, null);
        }
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (bitmap != null) {
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            canvas.drawBitmap(bitmap, 0, 0, paint);
            paint.setXfermode(null);
        }
    }

    public void setRadius(int radius) {
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, paint);
        invalidate();
    }

}


public class PullLayout extends ScrollView {

    private View rl_top;
    private View ll_weather;
    private View ll_content;
    private TextView tv;
    private EyeView ev;
    private ObjectAnimator oa;
    private float lastY = -1;
    private float detalY = -1;
    private int range;
    private int tvHeight;
    private int tvWidth;
    private boolean isTouchOrRunning;
    private boolean isActionCancel;

    public PullLayout(Context context) {
        super(context);
    }

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

    public PullLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setVerticalScrollBarEnabled(false);
        rl_top = findViewById(R.id.rl_top);
        ll_content = findViewById(R.id.ll_content);
        tv = (TextView) findViewById(R.id.tv);
        ev = (EyeView) findViewById(R.id.ev);
        ll_weather = findViewById(R.id.ll_weather);

        rl_top.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                rl_top.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                range = rl_top.getHeight();
                scrollTo(0, range);
                rl_top.getLayoutParams().height = range;
            }
        });
        tv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                tvHeight = tv.getHeight();
                tvWidth = tv.getWidth();
                ViewHelper.setTranslationY(ll_content, tvHeight);
            }
        });

        ev.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                close();
            }
        });

        tv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                open();
            }
        });

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isActionCancel = false;
                isTouchOrRunning = true;
                lastY = ev.getY();
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (oa != null && oa.isRunning()) {
            ev.setAction(MotionEvent.ACTION_UP);
            isActionCancel = true;
        }
        if (isActionCancel && ev.getAction() != MotionEvent.ACTION_DOWN) {
            return false;
        }
        if (ev.getActionIndex() != 0 && getScrollY() < range) {
            ev.setAction(MotionEvent.ACTION_UP);
            isActionCancel = true;
        }

        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                isTouchOrRunning = true;
                if (getScrollY() != 0) {
                    detalY = 0;
                    lastY = ev.getY();
                } else {
                    detalY = ev.getY() - lastY;
                    if (detalY > 0) {
                        setT((int) -detalY / 5);
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                isTouchOrRunning = false;
                if (getScrollY() < range) {
                    if (detalY != 0) {
                        reset();
                    } else {
                        toggle();
                    }
                    return true;
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (t > range) {
            return;
        } else if (!isTouchOrRunning && t != range) {
            scrollTo(0, range);
        } else {
            animateScroll(t);
        }
    }

    public void setT(int t) {
        scrollTo(0, t);
        if (t < 0) {
            animatePull(t);
        }
    }

    private void animateScroll(int t) {
        float percent = (float) t / range;
        ViewHelper.setTranslationY(rl_top, t);
        ViewHelper.setTranslationY(ll_content, tvHeight * percent);
        ViewHelper.setScaleX(tv, 2 - percent);
        ViewHelper.setScaleY(tv, 2 - percent);
        ViewHelper.setTranslationX(tv, tvWidth * (1 - percent) / 2f);
        ViewHelper.setTranslationY(tv, t + tvHeight * (1 - percent) / 2f);
        ViewHelper.setTranslationY(ev, -t / 2);
        ViewHelper.setTranslationY(ll_weather, -t / 2);
        ev.setRadius((int) (range * 0.25f * (1 - percent)));
        tv.setTextColor(evaluate(percent, Color.WHITE, Color.BLACK));
    }

    private void animatePull(int t) {
        rl_top.getLayoutParams().height = range - t;
        rl_top.requestLayout();
        float percent = (float) t / range;
        ViewHelper.setScaleX(ev, 1 - percent);
        ViewHelper.setScaleY(ev, 1 - percent);
        ViewHelper.setScaleX(tv, 2 - percent);
        ViewHelper.setScaleY(tv, 2 - percent);
        ViewHelper.setTranslationX(tv, tvWidth * (1 - percent) / 2f);
        ViewHelper.setTranslationY(ll_weather, t / 2);
    }

    private Integer evaluate(float fraction, Object startValue, Integer endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24) & 0xff;
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;
        int endInt = (Integer) endValue;
        int endA = (endInt >> 24) & 0xff;
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;
        return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
                | (int) ((startR + (int) (fraction * (endR - startR))) << 16)
                | (int) ((startG + (int) (fraction * (endG - startG))) << 8)
                | (int) ((startB + (int) (fraction * (endB - startB))));
    }

    public void toggle() {
        if (isOpen()) {
            close();
        } else {
            open();
        }
    }

    private Status status;

    public enum Status {
        Open, Close;
    }

    public boolean isOpen() {
        return status == Status.Open;
    }

    private void reset() {
        if (oa != null && oa.isRunning()) {
            return;
        }
        oa = ObjectAnimator.ofInt(this, "t", (int) -detalY / 5, 0);
        oa.setDuration(150);
        oa.start();
    }

    public void close() {
        if (oa != null && oa.isRunning()) {
            return;
        }
        oa = ObjectAnimator.ofInt(this, "t", getScrollY(), range);
        oa.setInterpolator(new DecelerateInterpolator());
        oa.addListener(new AnimatorListener() {
            @Override
            public void onAnimationStart(Animator arg0) {
                isTouchOrRunning = true;
            }

            @Override
            public void onAnimationRepeat(Animator arg0) {
            }

            @Override
            public void onAnimationEnd(Animator arg0) {
                isTouchOrRunning = false;
                status = Status.Close;
            }

            @Override
            public void onAnimationCancel(Animator arg0) {

            }
        });
        oa.setDuration(250);
        oa.start();
    }

    public void open() {
        if (oa != null && oa.isRunning()) {
            return;
        }
        oa = ObjectAnimator.ofInt(this, "t", getScrollY(), (int) (-getScrollY() / 2.2f), 0);
        oa.setInterpolator(new DecelerateInterpolator());
        oa.addListener(new AnimatorListener() {
            @Override
            public void onAnimationStart(Animator arg0) {
                isTouchOrRunning = true;
            }

            @Override
            public void onAnimationRepeat(Animator arg0) {
            }

            @Override
            public void onAnimationEnd(Animator arg0) {
                isTouchOrRunning = false;
                status = Status.Open;
            }

            @Override
            public void onAnimationCancel(Animator arg0) {

            }
        });
        oa.setDuration(400);
        oa.start();
    }

}



<com.bluemor.pulllayout.PullLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

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

            <ImageView
                android:id="@+id/iv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:src="@drawable/weather_bg_rain" />

            <com.bluemor.pulllayout.EyeView
                android:id="@+id/ev"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="30dp"
                android:background="@drawable/selector_bg" >

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:scaleType="centerCrop"
                    android:src="@drawable/eye" />
            </com.bluemor.pulllayout.EyeView>

            <LinearLayout
                android:id="@+id/ll_weather"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="30dp"
                android:layout_marginLeft="30dp"
                android:orientation="horizontal" >

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:drawableTop="@drawable/weather_mostly_cloudy"
                    android:gravity="center"
                    android:text="10°~17°\r\n星期三"
                    android:textColor="@android:color/white"
                    android:textSize="12sp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:drawableTop="@drawable/weather_drizzle"
                    android:gravity="center"
                    android:text="11°~18°\r\n星期四"
                    android:textColor="@android:color/white"
                    android:textSize="12sp" />
            </LinearLayout>
        </RelativeLayout>

        <FrameLayout
            android:id="@+id/fl_bottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/rl_top"
            android:background="#F4F4F4" >

            <LinearLayout
                android:id="@+id/ll_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:paddingBottom="50dp"
                android:paddingTop="10dp" >

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/clip" />

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/clip2" />

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/clip2" />
            </LinearLayout>
        </FrameLayout>

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="25dp"
            android:layout_marginRight="25dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/selector_bg"
            android:paddingBottom="5dp"
            android:paddingTop="5dp"
            android:text="BlueMor"
            android:textSize="25sp" />
    </RelativeLayout>

</com.bluemor.pulllayout.PullLayout>

demo下载地址:http://download.csdn.net/detail/u014600432/8291613

时间: 2024-08-06 03:45:46

类似微信下拉眼睛UI的相关文章

0126——动画(类似微信下拉眼睛)

效果图 首先你得画出这只眼睛,这是眼睛包括5个部分组成: 1 @property (strong, nonatomic) CAShapeLayer *eyeFirstLightLayer; 2 @property (strong, nonatomic) CAShapeLayer *eyeSecondLightLayer; 3 @property (strong, nonatomic) CAShapeLayer *eyeballLayer; 4 @property (strong, nonatom

PullDownListView高仿微信下拉眼睛出现动画

PullDownListView高仿微信下拉眼睛出现动画,动画自定义PullDownListView,pullDownListView.setOnPullHeightChangeListener设置下拉高度监听,onTopHeightChange()onBottomHeightChange(),onRefreshing()其中提供者三个方法时刻刷新页面特效 查看项目完整源码:http://www.itlanbao.com/code/20150911/10000/100524.html 引入布局:

超炫 PullDownListView高仿微信下拉眼睛出现动画

PullDownListView高仿微信下拉眼睛出现动画,动画自定义PullDownListView, pullDownListView.setOnPullHeightChangeListener设置下拉高度监听,onTopHeightChange() onBottomHeightChange(),onRefreshing()其中提供者三个方法时刻刷新页面特效 运行效果: 完整源码下载地址:http://www.itlanbao.com/code/20150911/10000/100524.ht

弹性ScrollView,和下啦刷新的效果类似 实现下拉弹回和上拉弹回

今天做了一个弹性ScrollView,和下啦刷新的效果类似,我想这个很多需求都用的这种效果 其实这是一个自定义的scrollView,上代码,这是我写在一个公共的组件包里的 package com.pb.soft.widget; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import

Android开发仿微信下拉关闭图片11

图片会跟随手指移动,只有是下滑时才会退出查看页面,其他情况会复位,直接当做ImageView使用即可,setViewCall方法是在下滑完成后要执行的操作,上,左,右,可自行扩展 onTouchEvent 监听手指坐标,GestureDetector 监听滑动的惯性,ViewHelper设置图片位移动画 public class FriendCircleView extends android.support.v7.widget.AppCompatImageView implements Ges

微信浏览器下拉黑边的终极解决方案---wScroollFix

开始 由于在开发微信页面的时候下拉黑边的情况很常见,有时候会比较影响体验,因此开发了wScrollFix库,用于隐藏微信下拉的黑边问题npm地址github地址 什么是黑边 相信很多在微信上面做网页开发的同学都会发现,当页面被划到顶部或者底部的时候,如果继续滑动,页面会被整个进行下滑,露出上面或者下面的黑底,黑底上面标明了当前访问页面的域名信息,黑边的作用也很明显,由于在微信内浏览器并没有像传统浏览器地址栏那样子的设计,为了在一定程度上面防止钓鱼网站,所以通过下拉显示域名信息,如下图Wechat

&lt;第三方&gt;TGRefreshO按照QQ的刷新方式下拉刷新

一 .使用方法: 刷新机制,类似QQ一样的刷新机制,弹簧.橡皮筋下拉刷新控件,类似QQ下拉刷新效果,同时支持其他样式: 首先写上这一句(必须的) #import <TGRefresh.h> 如果需要,在你的控制器中加上一句 self.automaticallyAdjustsScrollViewInsets=NO; QQ效果 self.tableview.tg_header = [TGRefreshOC  refreshWithTarget:self action:@selector(doRef

自个儿写Android的下拉刷新/上拉加载控件 (续)

本文算是对之前的一篇博文<自个儿写Android的下拉刷新/上拉加载控件>的续章,如果有兴趣了解更多的朋友可以先看一看之前的这篇博客. 事实上之所以会有之前的那篇博文的出现,是起因于前段时间自己在写一个练手的App时很快就遇到这种需求.其实我们可以发现类似这样下拉刷新.上拉加载的功能正在变得越来越普遍,可以说如今基本上绝大多数的应用里面都会使用到.当然,随着Android的发展,已经有不少现成的可以实现这种需求的"轮子"供我们使用了. 但转过头想一下想,既然本来就是自己练手

MDNavBarView下拉导航菜单(仿美团导航下拉菜单)

说到下拉导航菜单这个东西用得还真不少,细心算一下做开发以来这样的菜单已经写了第三次了,但基本都是不能复用.感觉特累人.不经意看到同事写一个类似的下拉菜单,但他引用了开源库仿大众菜单的库,大致看了一下,感觉挺不错的,复用性也比较好,但要 是换成别的样式就要去修改代码了,感觉这有点不方便也比较容易出错.于是参照他的大致思路写了一个仿下拉菜单. 具体的实现就不多说了,觉得有意思的话可以下来看看.下面说一下使用方法吧: 1.添加navbarview包下的代码与对应资源 2.布局文件中添加: <com.m