android 仿iphone上的财经资讯列表,层叠滚动效果

来源:互联网 发布:原始杀戮优化 编辑:程序博客网 时间:2024/04/28 06:24

先上个图


原理不难,直接上代码:(当前代码不支持android2.3和2.3以下的版本)

/******************************************************************** * Copyright    :   新英体育传媒集团                          © 2013 ssports.com 版权所有 *  * Filename     :   .java * Author       :   zhangxyfs * Date         :   2013-3-8 * Version      :   V1.00 * Description  :    * * History      :   Modify Id  |  Date  |  Origin  |  Description *******************************************************************/package com.scrollLayout;import java.util.ArrayList;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.RelativeLayout;import android.widget.Scroller;import android.widget.Toast;@SuppressLint("NewApi")public class ScrollLayout extends RelativeLayout {private static final String TAG = "ScrollLayout";private Context _context;private Scroller _scroller;/** 所有的子视图(正常的排序) */private ArrayList<View> _childViewList;/** 所有的子视图(为了显示层叠效果而生成的排序方式) */private ArrayList<View> _sortChildViewList;/** 屏幕上可以看到的视图+2, 例如:屏幕上有5个屏幕外有2个 */private ArrayList<View> _visiableChildViewList;/** 上移标识 */private static final int MOVETOUP = 0x100;/** 下移标识 */private static final int MOVETODOWN = 0x200;/** 默认屏幕上视图的个数(自动+2) */private int _visiableChildViewNumber = 7;/** 所有可见子视图缩放比例 列表 */private ArrayList<Float> _childScaleList;/** 所有可见子视图透明度列表 */private ArrayList<Float> _childAlphaList;/** 移动时候的缩放列表 */private ArrayList<Float> _childMoveToScaleList;/** 移动时候的透明度列表 */private ArrayList<Float> _childMoveToAlphaList;/** 所有可见子视图height */private ArrayList<Float> _childHeightList;/** 到中心的距离列表(中心以上是到中心上标,以下是到中心下标) */private ArrayList<Float> _childYList;/** 最大放大比例 */private float _maxScale = 1.5f;/** 相邻比例间差值 */private float _scaleDVale = 0.2f;/** 最大的透明度 */private float _maxAlpha = 1f;/** 相邻透明度间差值 */private float _alphaDVale = 0.2f;/** 最后一次滑动的距离 */private float _lastionMotionY = 0;/** 移动距离 */private int move = 0;/** 跳转activity需要 */private Activity _fromActivity = null;/** 跳转activity需要 */private Class _toClass = null;/** 跳转传参标识 */private String _flag = null;/** 跳转要传递的参数 */private int _value = 0;/** 屏幕的高度 */private float _screenHeight = 1230f;public ScrollLayout(Context context) {super(context);_context = context;_scroller = new Scroller(context);}public ScrollLayout(Context context, AttributeSet attrs) {super(context, attrs);_context = context;_scroller = new Scroller(context);}public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);_context = context;_scroller = new Scroller(context);}/** 自定义屏幕上显示子视图的个数(默认为5) */public void setVisiableViewNumber(int visiableViewNumber) {if (visiableViewNumber % 2 == 0) {Toast.makeText(_context, "显示在屏幕上的子视图个数不能为偶数", Toast.LENGTH_SHORT).show();} else {this._visiableChildViewNumber = visiableViewNumber + 2;}}/** 设置屏幕的高度 */public void setScreenHeight(float sh) {_screenHeight = sh;}/** * 初始化 *  * @param viewList *            子视图列表 * @param activity *            跳转activity需要 * @param clzz *            跳转activity需要 * @param flag *            跳转传参标识 * @param value *            跳转要传递的参数 */public void init(ArrayList<View> viewList, Activity fromActivity, Class toClass, String flag, int value) {_fromActivity = fromActivity;_toClass = toClass;_flag = flag;_value = value;_childViewList = viewList;initView();}/** * 初始化 *  * @param viewList *            子视图列表 * @param fromActivity *            跳转activity需要 * @param toClass *            跳转activity需要 */public void init(ArrayList<View> viewList, Activity fromActivity, Class toClass) {_fromActivity = fromActivity;_toClass = toClass;_childViewList = viewList;initView();}/** * 初始化 *  * @param viewList *            子视图列表 */public void init(ArrayList<View> viewList) {_childViewList = viewList;initView();}/** * 初始化子视图 */private void initView() {sortView();createVisiableChildView();addVisiableChildView();createVisiableChildScaleList();createVisiableChildAlphaList();}/** * 设置可见视图(_visiableChildViewList)的缩放比例和透明度 *  * @param scale *            最大放大比例 * @param dValue *            相邻比例间差值 * @param maxAlpha *            最大透明度 * @param alphaDVale *            相邻透明度间差值 */public void setVisiableChildScale(float scale, float scaleDValue, float maxAlpha, float alphaDVale) {_maxScale = scale;_scaleDVale = _alphaDVale;_maxAlpha = maxAlpha;_alphaDVale = alphaDVale;}/** * 生成可见视图(_visiableChildViewList)透明度列表(中间为1) */private void createVisiableChildAlphaList() {_childAlphaList = new ArrayList<Float>();for (int i = _visiableChildViewList.size() / 2; i >= 0; i--) {_childAlphaList.add(_maxAlpha - (float) i * _alphaDVale);_childAlphaList.add(_maxAlpha - (float) i * _alphaDVale);}_childAlphaList.remove(_childAlphaList.size() - 1);}/** * 生成可见视图(_visiableChildViewList)的缩放列表 */private void createVisiableChildScaleList() {_childScaleList = new ArrayList<Float>();for (int i = _visiableChildViewList.size() / 2; i >= 0; i--) {_childScaleList.add(_maxScale - (float) i * _scaleDVale);_childScaleList.add(_maxScale - (float) i * _scaleDVale);}_childScaleList.remove(_childScaleList.size() - 1);}/** * 生成可见视图(_visiableChildViewList)高度列表 */private void createVisiableChildHeightList(ArrayList<Float> childScaleList) {_childHeightList = new ArrayList<Float>();float height = getChildAt(0).getMeasuredHeight();for (int i = 0; i < _visiableChildViewList.size(); i++) {_childHeightList.add(height * childScaleList.get(i));}}/** * 生成可见视图(_visiableChildViewList)Y坐标 */private void createVisiableChildYList() {_childYList = new ArrayList<Float>();float value = Math.abs(_screenHeight - getY() - getMeasuredHeight() - getY());float centerChildUpY = ((float) getMeasuredHeight() - _childHeightList.get(_childHeightList.size() - 1)) / 2f;float centerChildDownY = centerChildUpY + _childHeightList.get(_childHeightList.size() - 1);for (int i = 0; i < _visiableChildViewList.size() - 1; i = i + 2) {float height = 0;for (int j = i; j < _visiableChildViewList.size() - 1; j = j + 2) {height += _childHeightList.get(j) * 3 / 4;}_childYList.add(centerChildUpY - height + getY());height = 0;for (int j = i + 1; j < _visiableChildViewList.size() - 1; j = j + 2) {height += _childHeightList.get(j) * 3 / 4;}_childYList.add(centerChildDownY + height - _childHeightList.get(i + 1) + value);}_childYList.add(centerChildUpY + getY());}/** * 将子视图列表(_childViewList)重新排序,生成(_sortChildViewList) */private void sortView() {_sortChildViewList = new ArrayList<View>();ArrayList<View> temp = new ArrayList<View>();copyList(_childViewList, temp);// 如果子视图列表size是偶数if (temp.size() % 2 == 0) {_sortChildViewList.add(temp.get(0));temp.remove(0);}while (temp.size() > 1) {_sortChildViewList.add(temp.get(0));_sortChildViewList.add(temp.get(temp.size() - 1));temp.remove(0);temp.remove(temp.size() - 1);}if (temp.size() == 1) {_sortChildViewList.add(temp.get(0));}}/** * 生成可见视图(_visiableChildViewList) */private void createVisiableChildView() {_visiableChildViewList = new ArrayList<View>();int start = _sortChildViewList.size() - _visiableChildViewNumber;for (int i = start; i < _sortChildViewList.size(); i++) {_visiableChildViewList.add(_sortChildViewList.get(i));}}/** * 删除原有子视图,装载可见视图(_visiableChildViewList)到父视图中 */private void addVisiableChildView() {removeAllViews();for (int i = 0; i < _visiableChildViewList.size(); i++) {addView(_visiableChildViewList.get(i));}}/** * 循环排列子视图列表(_childViewList)重新生成可见视图并装载到父视图中 *  * @param moveDirection *            移动方向 */private void cycleSortChildViews(int moveDirection) {ArrayList<View> temp = new ArrayList<View>();View view;if (moveDirection == MOVETOUP) {view = _childViewList.get(0);_childViewList.remove(0);_childViewList.add(view);}if (moveDirection == MOVETODOWN) {view = _childViewList.get(_childViewList.size() - 1);_childViewList.remove(_childViewList.size() - 1);temp.add(view);copyList(_childViewList, temp);_childViewList = temp;}}/** * 子视图放大或缩小 *  * @param scale */private void scaleChildView(int position, float scale) {getChildAt(position).setScaleX(scale);getChildAt(position).setScaleY(scale);}/** 获取子视图左面的坐标 */private int getChildViewLeft(int position) {return (getMeasuredWidth() - getChildAt(position).getMeasuredWidth()) / 2;}/** 获取子视图右面的坐标 */private int getChildViewRight(int position) {return getChildViewLeft(position) + getChildAt(position).getMeasuredWidth();}/** 获得子视图的高度 */private int getChildViewHeight(int position) {return getChildAt(position).getMeasuredHeight();}/** 获取中间子视图上面的坐标 */private int getCenterChildViewTop() {return (getMeasuredHeight() - getChildAt(getChildCount() - 1).getMeasuredHeight()) / 2;}/** 获取中间子视图下面的坐标 */private int getCenterChildViewBottom() {return getCenterChildViewTop() + getChildAt(getChildCount() - 1).getMeasuredHeight();}/** * 实现移动 *  * @param dy */private void moveTo(int dy) {scrollBy(0, dy);move += dy;// 下移if (move < 0) {_childMoveToScaleList = createMoveToProperty(move, _childScaleList, _scaleDVale, 0f);_childMoveToAlphaList = createMoveToProperty(move, _childAlphaList, _alphaDVale, 1f);scaleAlphaAndMoveChild();if (_childMoveToScaleList.get(_childMoveToScaleList.size() - 3) > _maxScale) {cycleSortChildViews(MOVETODOWN);sortView();createVisiableChildView();addVisiableChildView();createVisiableChildScaleList();createVisiableChildAlphaList();scrollBy(0, -move);move = 0;requestLayout();}}// 上移if (move >= 0) {_childMoveToScaleList = createMoveToProperty(move, _childScaleList, _scaleDVale, 0f);_childMoveToAlphaList = createMoveToProperty(move, _childAlphaList, _alphaDVale, 1f);scaleAlphaAndMoveChild();if (_childMoveToScaleList.get(_childMoveToScaleList.size() - 2) > _maxScale) {cycleSortChildViews(MOVETOUP);sortView();createVisiableChildView();addVisiableChildView();createVisiableChildScaleList();createVisiableChildAlphaList();scrollBy(0, -move);move = 0;requestLayout();}}}/** * 实现动画(移动,透明度变化,缩放) */private void scaleAlphaAndMoveChild() {if (_childMoveToScaleList.size() > 2 && _childMoveToAlphaList.size() > 2) {for (int i = 0; i < getChildCount(); i++) {scaleChildView(i, _childMoveToScaleList.get(i));getChildAt(i).setAlpha(_childMoveToAlphaList.get(i));}createVisiableChildHeightList(_childMoveToScaleList);createVisiableChildYList();toLayout();}}/** * 生成移动时候的属性(透明度列表或缩放列表) *  * @param move *            移动距离 * @param propertyList *            _childScaleList或者_childAlphaList * @param dValue *            差值 * @param centerProperty *            中间的值 * @return 移动时候需要生成的列表 */private ArrayList<Float> createMoveToProperty(int move, ArrayList<Float> propertyList, float dValue,float centerProperty) {ArrayList<Float> moveToList = new ArrayList<Float>();ArrayList<Float> tempA = new ArrayList<Float>();ArrayList<Float> tempB = new ArrayList<Float>();int tempMove = Math.abs(move);float property = 0f;int end = propertyList.size() - 1;// 向下移动if (move < 0) {for (int i = 0; i < _childHeightList.size() - 1; i = i + 2) {property = dValue / (_childHeightList.get(i + 2) - _childHeightList.get(i) / 4) * (float) tempMove+ propertyList.get(i);tempA.add(property);}for (int i = 1; i < _childHeightList.size(); i = i + 2) {if (i == 1) {property = propertyList.get(1);} else {property = propertyList.get(i) - dValue/ (_childHeightList.get(i - 2) - _childHeightList.get(i) / 4) * (float) tempMove;}tempB.add(property);}centerProperty = propertyList.get(end) - dValue/ (_childHeightList.get(end - 1) - _childHeightList.get(end) / 4) * (float) tempMove;}// 向上移动if (move >= 0) {for (int i = 0; i < _childHeightList.size() - 1; i = i + 2) {if (i == 0) {property = propertyList.get(0);} else {property = propertyList.get(i) - dValue/ (_childHeightList.get(i - 2) - _childHeightList.get(i) / 4) * (float) tempMove;}tempA.add(property);// Log.e(TAG, scale+"");}for (int i = 1; i < _childHeightList.size(); i = i + 2) {if (i + 2 < _childHeightList.size()) {property = dValue / (_childHeightList.get(i + 2) - _childHeightList.get(i) / 4) * (float) tempMove+ propertyList.get(i);} else {property = dValue / (_childHeightList.get(i + 1) - _childHeightList.get(i) / 4) * (float) tempMove+ propertyList.get(i);}tempB.add(property);}centerProperty = propertyList.get(end) - dValue/ (_childHeightList.get(end) - _childHeightList.get(end - 1) / 4) * (float) tempMove;}for (int i = 0; i < tempA.size(); i++) {moveToList.add(tempA.get(i));moveToList.add(tempB.get(i));}moveToList.add(centerProperty);return moveToList;}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 手指位置地点float Y = event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 如果屏幕的动画还没结束,你就按下了,我们就结束该动画if (_scroller != null) {if (!_scroller.isFinished()) {_scroller.abortAnimation();}}_lastionMotionY = Y;break;case MotionEvent.ACTION_MOVE:moveTo((int) (_lastionMotionY - Y));_lastionMotionY = Y;break;case MotionEvent.ACTION_UP:if (_fromActivity != null && _toClass != null) {if (Math.abs(Y - event.getY()) < 5) {if ((event.getY() > getCenterChildViewTop() && event.getY() < getCenterChildViewBottom())&& (event.getX() > getChildViewLeft(getChildCount() - 1) && event.getX() < getChildViewRight(getChildCount() - 1))) {if (_flag != null) {openActivity(_fromActivity, _toClass, _flag, _value);} else {openActivity(_fromActivity, _toClass);}}}}// 下移if (move < 0) {scrollBy(0, -move);move = 0;requestLayout();}// 上移if (move > 0) {scrollBy(0, -move);move = 0;requestLayout();}break;case MotionEvent.ACTION_CANCEL:break;}return true;}/** * 只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用 */@Overridepublic void computeScroll() {// 如果返回true,表示动画还没有结束// 因为前面startScroll,所以只有在startScroll完成时 才会为falseif (_scroller.computeScrollOffset()) {// 产生了动画效果 每次滚动一点scrollTo(_scroller.getCurrX(), _scroller.getCurrY());// 刷新View 否则效果可能有误差postInvalidate();}}// measure过程@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);measureChildren(widthMeasureSpec, heightMeasureSpec);setMeasuredDimension(width, height);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {createVisiableChildHeightList(_childScaleList);createVisiableChildYList();toLayout();for (int i = 0; i < getChildCount(); i++) {scaleChildView(i, _childScaleList.get(i));}for (int i = 0; i < getChildCount(); i++) {getChildAt(i).setAlpha(_childAlphaList.get(i));}}/** * 重新刷新子视图的位置 */private void toLayout() {for (int i = 0; i < getChildCount(); i += 2) {getChildAt(i).layout(getChildViewLeft(i), (int) Math.rint(_childYList.get(i)), getChildViewRight(i),(int) Math.rint(_childYList.get(i)) + getChildViewHeight(i));if (i + 1 < getChildCount()) {getChildAt(i + 1).layout(getChildViewLeft(i + 1), (int) Math.rint(_childYList.get(i + 1)),getChildViewRight(i + 1), (int) Math.rint(_childYList.get(i + 1)) + getChildViewHeight(i + 1));}}}/** * 测试输出用 *  * @param list * @param str */private void LOG(ArrayList list, String str) {for (int i = 0; i < list.size(); i++) {Log.e(TAG, list.get(i) + str);}}/** * 拷贝列表 *  * @param from * @param to */private void copyList(ArrayList from, ArrayList to) {for (int i = 0; i < from.size(); i++) {to.add(from.get(i));}}/** * 打开新的页面 *  * @param activity * @param clzz * @param strValue * @param value */private void openActivity(Activity activity, Class clzz, String strValue, int value) {Intent intent = new Intent(activity, clzz);intent.putExtra(strValue, value);activity.startActivity(intent);System.gc();}/** * 打开新的页面 *  * @param activity * @param clzz */private void openActivity(Activity activity, Class clzz) {activity.startActivity(new Intent(activity, clzz));}}


调用方式:

<com.scrollLayout.ScrollLayout        android:id="@+id/scrollLayout"        android:layout_width="fill_parent"        android:layout_height="fill_parent" />


private ScrollLayout scrollLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);scrollLayout = (ScrollLayout) findViewById(R.id.scrollLayout);scrollLayout.setScreenHeight(1230f);scrollLayout.setVisiableViewNumber(5);scrollLayout.setVisiableChildScale(1.7f, 0.2f, 1f, 0.2f);scrollLayout.init(getViewList());}



说明:

scrollLayout.setScreenHeight(1230f); 这个参数需要传入的高度为 屏幕的高度-状态条高度-title的高度, 默认为1230

scrollLayout.setVisiableViewNumber(5);可以设置可见的子视图数量,默认为5

scrollLayout.setVisiableChildScale(1.7f, 0.2f, 1f, 0.2f);设置可见视图的缩放比例和透明度

scrollLayout.init(getViewList());初始化,需要传入子视图列表,有3种初始化方式,直接看代码好了,注释写的很清楚,需要注意的是,应该在设置完基本参数后进行初始化


下载地址:http://download.csdn.net/download/zhangxyfs/5133259

下载地址的代码有点问题,需要重新设置scrollLayout.setScreenHeight(xxxf)