• 9.视差特效、回弹动画、overScrollBy


    视差特效 
    应用场景: 微信朋友圈, QQ空间, 微博个人展示,向下拉出,松开回弹
    功能实现:
    > 1. 重写overScrollBy

    > 2. 松手之后执行动画, 类型估值器

    activity_main
    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:context=".MainActivity" >
          <com.itheima.parallaxdemo.ui.MyListView
              android:id="@+id/lv"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
      </RelativeLayout>
    view_header
    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical" >
          <ImageView
              android:id="@+id/iv"
              android:layout_width="match_parent"
              android:layout_height="160dp"
              android:scaleType="centerCrop"
              android:src="@drawable/parallax_img" />
      </LinearLayout>
    MyListView
    1. /**
       * 视差特效ListView
       * overScrollBy
       * @author poplar
       *
       */
      public class MyListView extends ListView {
      	private static final String TAG = "TAG";
      	private int mOriginalHeight;
      	private int drawableHeight;
      	private ImageView mImage;
      	public MyListView(Context context, AttributeSet attrs, int defStyle) {
      		super(context, attrs, defStyle);
      	}
      	public MyListView(Context context, AttributeSet attrs) {
      		super(context, attrs);
      	}
      	public MyListView(Context context) {
      		super(context);
      	}
      	
      	/**
      	 * 设置ImageView图片, 拿到引用
      	 * @param mImage
      	 */
      	public void setParallaxImage(ImageView mImage) {
      		this.mImage = mImage;
      		mOriginalHeight = mImage.getHeight(); // 160
      		drawableHeight = mImage.getDrawable().getIntrinsicHeight(); // 488,图片的高,而不是显示的高
      		
      		Log.d(TAG, "height: " + mOriginalHeight + " drawableHeight: " + drawableHeight);
      	}
      	
      	@Override
      	protected boolean overScrollBy(int deltaX, int deltaY, 
      			int scrollX, int scrollY, int scrollRangeX, int scrollRangeY,
      			int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
      		// deltaY : 竖直方向的瞬时偏移量 / 变化量 dx   顶部到头下拉为-, 底部到头上拉为+
      		// scrollY : 竖直方向的偏移量 / 变化量
      		// scrollRangeY : 竖直方向滑动的范围
      		// maxOverScrollY : 竖直方向最大滑动范围
      		// isTouchEvent : 是否是手指触摸滑动, true为手指, false为惯性
      		
      		Log.d(TAG, "deltaY: " +deltaY + " scrollY: " + scrollY + " scrollRangeY: " + scrollRangeY
      				+ " maxOverScrollY: " + maxOverScrollY + " isTouchEvent: " + isTouchEvent);
      		
      		// 手指拉动 并且 是下拉
      		if(isTouchEvent && deltaY < 0){
      			// 把拉动的瞬时变化量的绝对值交给Header, 就可以实现放大效果
      			if(mImage.getHeight() <= drawableHeight){
      				int newHeight = (int) (mImage.getHeight() + Math.abs(deltaY / 3.0f));
      			
      				// 高度不超出图片最大高度时,才让其生效
      				mImage.getLayoutParams().height = newHeight;
      				mImage.requestLayout();
      			}
      		}
      		
      		return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
      				scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
      	}
      	
      	@Override
      	public boolean onTouchEvent(MotionEvent ev) {
      		
      		switch (ev.getAction()) {
      			case MotionEvent.ACTION_UP:
      				// 执行回弹动画, 方式一: 属性动画值动画
      				// 从当前高度mImage.getHeight(), 执行动画到原始高度mOriginalHeight
      				final int startHeight = mImage.getHeight();
      				final int endHeight = mOriginalHeight;
      				
      //				valueAnimator(startHeight, endHeight);
      				// 执行回弹动画, 方式二: 自定义Animation
      				ResetAnimation animation = new ResetAnimation(mImage, startHeight, endHeight);
      				startAnimation(animation);
      				
      				break;
      		}
      		return super.onTouchEvent(ev);
      	}
      	private void valueAnimator(final int startHeight, final int endHeight) {
      		ValueAnimator mValueAnim = ValueAnimator.ofInt(1);//不起作用,写几都行
      		mValueAnim.addUpdateListener(new AnimatorUpdateListener() {
      			
      			@Override
      			public void onAnimationUpdate(ValueAnimator mAnim) {
      				float fraction = mAnim.getAnimatedFraction();
      				// percent 0.0 -> 1.0
      				Log.d(TAG, "fraction: " +fraction);
      				Integer newHeight = evaluate(fraction, startHeight, endHeight);//固值器
      				mImage.getLayoutParams().height = newHeight;//设置imageview高度
      				mImage.requestLayout();
      			}
      		});
      		
      		mValueAnim.setInterpolator(new OvershootInterpolator());
      		mValueAnim.setDuration(500);
      		mValueAnim.start();
      	}
      	
          public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
              int startInt = startValue;
              return (int)(startInt + fraction * (endValue - startInt));
          }
      	
      	
      }
    ResetAnimation
    1. public class ResetAnimation extends Animation {
      	private final ImageView mImage;
      	private final int startHeight;
      	private final int endHeight;
      	public ResetAnimation(ImageView mImage, int startHeight, int endHeight) {
      		this.mImage = mImage;
      		this.startHeight = startHeight;
      		this.endHeight = endHeight;
      		
      		setInterpolator(new OvershootInterpolator());
      		//设置动画执行时长
      		setDuration(500);
      	}
      	@Override
      	protected void applyTransformation(float interpolatedTime, Transformation t) {
      		// interpolatedTime 0.0f -> 1.0f
      		
      		Integer newHeight = evaluate(interpolatedTime, startHeight, endHeight);
      		mImage.getLayoutParams().height = newHeight;//设置imageview高
      		mImage.requestLayout();
      		
      		super.applyTransformation(interpolatedTime, t);
      	}
      	
      	
          /**
           * 类型估值器
           * @param fraction
           * @param startValue
           * @param endValue
           * @return
           */
          public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
              int startInt = startValue;
              return (int)(startInt + fraction * (endValue - startInt));
          }
      	
      	
      	
      }
      
    2.   MainActivity

    3. public class MainActivity extends Activity {
      	@Override
      	protected void onCreate(Bundle savedInstanceState) {
      		super.onCreate(savedInstanceState);
      		setContentView(R.layout.activity_main);
      		
      		
      		final MyListView mListView = (MyListView) findViewById(R.id.lv);
      		mListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
      		// 加Header
      		final View mHeaderView = View.inflate(MainActivity.this, R.layout.view_header, null);
      		final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
      		mListView.addHeaderView(mHeaderView);
      		
      		mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
      			
      			@Override
      			public void onGlobalLayout() {
      				// 当布局填充结束之后, 此方法会被调用
      				mListView.setParallaxImage(mImage);
      				
      				mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      			}
      		});
      		
      		// 填充数据
      		mListView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES));
      		
      	}
      }
      
  • 相关阅读:
    JAVA中字符串比较equals()和equalsIgnoreCase()的区别
    idea无法调试的解决方案.
    idea如何把快捷键改成eclipse的快捷键
    idea安装和破解教程
    在idea中maven项目 jar包下载不完整解决办法
    Spring boot入门级项目(超详细简易版)
    123123
    ww
    无限极操作
    无限极菜单1
  • 原文地址:https://www.cnblogs.com/sixrain/p/5041944.html
Copyright © 2020-2023  润新知