Android视觉动画效果---未完待续
来源:互联网 发布:比价系统源码 编辑:程序博客网 时间:2024/05/29 17:24
最近公司项目要求这个效果,搜来搜去,我都没有找到类似的效果,IOS倒是有类似的Demo,于是乎,自己写了一个体验很差的这种效果,希望大家能够及时指正,并且能开阔新领域。共同进步,如果你的项目有用到类似效果,也请留言,让大家互相学习。
1:原理就是滑动的过程当中不断的计算条目的高度。并且这个高度是根据滑动的距离算出来的
2:透明度不断变化,你会看到第一个透明度是比其他的透明度亮了许多的,其实透明度也是一个根据滑动距离逐渐变化的过程,
在做这个的时候,遇到了几个问题,希望告诉大家,如果大家有什么意见也可以评论。
1 :是自定义ListView的时候,如果你首先设置了滑动监听,那么他会首先执行OnScroll方法,其次执行Onlayout方法,并且一般一次的Onlayot是不能把所有的子布局给初始化好的,因为第一次调用getChildCount方法,得到不是一个正确的子数目的个数。一般第二次或第三次调用Onlayout才是正确的getchildCount数目,如果你想跟IOS一样通过一次遍历得到所有初始化的条目的Y坐标,进而实现这个效果,目前不太可能。因为Android 中ListView遍历的getChildCount方法,只是获得到了显示在屏幕中的那几个条目数,并不是所有的。
2:通过不断的通过:
LinearLayout layout = ( LinearLayout) view.getChildAt(i); AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) itemHeight); layout.setLayoutParams(layoutParams);
这种方式不断的去设置条目的大小,是会跟onscroll()方法造成一个死循环的,因为每次设置条目的尺寸,都会先执行OnScroll()然后接着就执行onlayout();事想假如你不断的滚动不断的设置,设置的同时又调用了Onscroll这不就是一个死循环么?
3:计算不准确,因为我们这个条目的尺寸的时候,强制要求的是整形 ,这样经过四舍五入,有时候也会出现精确度的误差。
4:再滑动到最后的时候,还要继续往上能够滑动,直到最后一个条目到了屏幕的最上面,目前我只是加了几个footer让条目继续往上能够滑动了,这到后面肯定是有问题的。 IOS是通过一个ContentSize即设置了listView的高度大于实际条目的高度的多少,让其继续能够往上滚动的,我通过设置listView的高并没有实现类似的效果,即,依然滑到最底部之后,不能往上继续滚动。希望大家能够提出自己的建议。
原理讲清楚,下面附上代码,
package sample.discrollview.flavienlaurent.com.mylistview;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.database.sqlite.SQLiteCantOpenDatabaseException;import android.graphics.Canvas;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.LinearLayout;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Toast;import com.nineoldandroids.view.ViewHelper;public class LvListView extends ListView implements AbsListView.OnScrollListener{ /** * 显示在屏幕上多少个item */ private int showItemCount; /** * 每个item的高度 */ private int itemHeight; /** * 记录第一个显示的item */ /** * 从第几行执行动画 */ private int scaleFlagIndex = 1; /** * 是否到了最后一行 */ private boolean lastFlag = false; /** * 步骤 */ private int step = 0; /** * 步骤个数 */ private int stepCount; private Context context; private boolean isScroll=false; private float lastY; private float maxAlpha=0.45f; //设置顶部条目的标准 private int TopItem=400; //设置下面的item布局 private int BottomItem=200; //记录是否是第一次进去onlayout的遍历for private Boolean isFirs=true; private int a; private Boolean isRealyScroll=false; //初始Padding private float FirstPadding=85f; private float TwoPadding=285f; private float RecordItemOHeight; private int mFirstVisibleItem; private Boolean addFooter=true; private View viewFooter; public LvListView(Context context) { this(context, null); this.context=context; } public LvListView(Context context, AttributeSet attrs) { this(context, attrs, 0); this.context=context; } /** * 构造方法中拿到自定义属性showViewCount,并设置滚动监听 * * @param context * @param attrs * @param defStyleAttr */ public LvListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context=context; //获取showViewCount TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LvListView); showItemCount = typedArray.getInt(R.styleable.LvListView_showViewCount, 0); typedArray.recycle(); //设置一个滚动监听 setOnScrollListener(this); } /* @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }*/ /* @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_UP) { checkForReset(); return true; } return super.onTouchEvent(ev); }*/ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); isScroll=true; if(isFirs) { //写个方法解决,布局黑的问题 for (int i = 0; i < getChildCount(); i++) { if (i == 0) { getChildAt(i).findViewById(R.id.textview).setAlpha(0); getChildAt(i).findViewById(R.id.textview_xiantop).setAlpha(1); getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, TopItem)); } else { getChildAt(i).findViewById(R.id.textview).setAlpha(1); getChildAt(i).findViewById(R.id.textview_xiantop).setAlpha(0); getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, BottomItem)); } } } if(!isRealyScroll) { initLayot(); } stepCount = getAdapter().getCount() - 2; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } /** * 检查当前getScrollY,显示完成Item,或者收缩此Item */ private void checkForReset() { int top = getChildAt(0).getTop(); if (top == 0) return; Log.d("==",top+""); if (Math.abs(top) > 130) { this.smoothScrollBy((int)RecordItemOHeight-Math.abs(top), 100); } else if(Math.abs(top)>95&&Math.abs(top)<130) { return; }else { this.smoothScrollBy(-Math.abs(top),100); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { checkForReset(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(totalItemCount == 0) return; mFirstVisibleItem = firstVisibleItem; if(isScroll&&getChildAt(0).getY()!=lastY) { Log.d("onScroll","执行了onSrcoll"); isFirs=false; isRealyScroll=true; for (int i = 0; i < getChildCount(); i++) { float item0Height = getChildAt(0).getY(); if (i == 0) { float itemHeight = 400.0f + item0Height / getChildAt(0).getHeight() * 200.0f; this.RecordItemOHeight=itemHeight; LinearLayout layout = (LinearLayout) getChildAt(i); AbsListView.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int)itemHeight); layout.setLayoutParams(layoutParams); getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.textview).setAlpha(1 - gettextAlphaNumber(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.textview_xiantop).setAlpha(gettextAlphaNumber(TopItem, BottomItem, itemHeight)); // getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int) getPadding(TopItem, BottomItem, itemHeight)); if (getChildAt(0).getY()>lastY) {// getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int) getPadding(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int) FirstPadding); getChildAt(i).findViewById(R.id.textview).setPadding(0, 0, 0, (int) FirstPadding); getChildAt(i).findViewById(R.id.textview_xiantop).setPadding(0, 0, 0, (int) FirstPadding); Log.d("lastY","getChildAt(0).getY()"+getChildAt(0).getY()+" >lastY"+lastY); } lastY=item0Height; } else if(i == 1) { float itemHeight = 200.0f - item0Height / getChildAt(0).getHeight() * 200.0f; getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, itemHeight)); LinearLayout layout = ( LinearLayout) view.getChildAt(i); AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) itemHeight); layout.setLayoutParams(layoutParams); getChildAt(i).findViewById(R.id.textview).setAlpha(1 - gettextAlphaNumber(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.textview_xiantop).setAlpha(gettextAlphaNumber(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int) getPadding(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.textview).setPadding(0, 0, 0, (int) getPadding(TopItem, BottomItem, itemHeight)); getChildAt(i).findViewById(R.id.textview_xiantop).setPadding(0, 0, 0, (int) getPadding(TopItem, BottomItem, itemHeight)); } else { itemHeight = 200; getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, itemHeight)); LinearLayout layout = (LinearLayout) getChildAt(i); AbsListView.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight); layout.setLayoutParams(layoutParams); getChildAt(i).findViewById(R.id.textview).setAlpha(1); getChildAt(i).findViewById(R.id.textview_xiantop).setAlpha(0); getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int) TwoPadding); getChildAt(i).findViewById(R.id.textview).setPadding(0, 0, 0, (int) TwoPadding); getChildAt(i).findViewById(R.id.textview_xiantop).setPadding(0, 0, 0, (int) TwoPadding); } } }else { return; }} public void initLayot() { for (int i = 0; i < getChildCount(); i++) { float item0Height = getChildAt(0).getY(); Log.d("item0Height", item0Height + ""); lastY = item0Height; if (i == 0) { //itemHeight = 450; float itemHeight = 400.0f + item0Height / getChildAt(0).getHeight() * 200.0f; getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, 400)); LinearLayout layout = (LinearLayout) getChildAt(i); AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) 400); layout.setLayoutParams(layoutParams); getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0, (int)FirstPadding); getChildAt(i).findViewById(R.id.textview).setPadding(0, 0, 0, (int)FirstPadding); getChildAt(i).findViewById(R.id.textview_xiantop).setPadding(0, 0, 0,(int)FirstPadding); } else { float itemHeight = 200.0f - item0Height / getChildAt(0).getHeight() * 200.0f; getChildAt(i).findViewById(R.id.ivtwo).setAlpha(getAlphaNumber(TopItem, BottomItem, 200)); LinearLayout layout = (LinearLayout) getChildAt(i); AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) 200); layout.setLayoutParams(layoutParams); getChildAt(i).findViewById(R.id.money).setPadding(0, 0, 0,(int)TwoPadding); getChildAt(i).findViewById(R.id.textview).setPadding(0, 0, 0, (int)TwoPadding); getChildAt(i).findViewById(R.id.textview_xiantop).setPadding(0, 0, 0,(int)TwoPadding); } } }//Topstandard目前设置为450, BottomStand目前定为300,currentItemHeight算出来的当前的tem高public float getAlphaNumber(float Topstandard, float BottomStand ,float currentItemHeight){ float delta=1-(Topstandard-currentItemHeight)/(Topstandard-BottomStand); float alpha=0.45f-(delta*(maxAlpha - 0.1f)); return alpha;} //Topstandard目前设置为450, BottomStand目前定为300,currentItemHeight算出来的当前的tem高 public float gettextAlphaNumber(float Topstandard, float BottomStand ,float currentItemHeight) { float delta=1-(Topstandard-currentItemHeight)/(Topstandard-BottomStand); return delta; } //Topstandard目前设置为450, BottomStand目前定为300,currentItemHeight算出来的当前的tem高 public float getPadding(float Topstandard, float BottomStand ,float currentItemHeight) {// float delta=(Topstandard-currentItemHeight)/(Topstandard-BottomStand);// float padding=100f-(delta*(100f - 10f));// return padding; float delta=(Topstandard-currentItemHeight)/(Topstandard-BottomStand); float padding=FirstPadding-(delta*(FirstPadding - TwoPadding)); return padding; }}
0 0
- Android视觉动画效果---未完待续
- android基础知识-未完待续
- android - Dialog(未完待续)
- 未完待续
- 未完待续
- 未完待续
- 未完,待续
- 未完待续~~~~~~~~~~~~~~~~
- 未完待续
- 未完待续
- 未完待续
- 未完待续
- 未完待续
- Android反编译方法(未完待续中...)
- Android - Calendar Provider(未完待续)
- android适配器的概念(未完待续)
- android Studio Gradle 自己摸索(未完待续)
- Android Studio使用总结 [未完待续]
- leetcode:N-Queens 【Java】
- 关于python中,map,reduce,filter,sort函数的用法:
- 点击标签实现特殊样式及阻止hove样式
- Unix的前世今生
- epoll函数的使用
- Android视觉动画效果---未完待续
- C#获取当前日期时间
- SimpleAdapter
- JAVA笔记之equals方法
- 论文查找地址
- JQuery实现一键返回顶部
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- Android属性动画完全解析(上),初识属性动画的基本用法
- HTML5本地存储