您的位置:首页 > 移动开发 > Android开发

Android仿京东首页画轴效果

2016-12-12 18:40 316 查看
记得之前京东首页有一个效果,有一个画轴,然后可以滚动画轴,去打开画(不知道怎么去形容这个效果,就叫做画轴效果吧- -!),然后去做相关操作,刚开始看到这个效果,想法是动态的去改变一个ImageView的高度,基本效果也就出来了,不过滚动部分的内容,当时接触的也不是很多,只是看过一些大牛的博客,略微了解了一点,当时也忙着写项目,也就没去多想,前些天忽然想到这个效果,就想着实现一下,不过京东新版本好像去掉这个东西了,只能凭着自己的记忆来大概搞一下,也是对滑动这部分内容的一个小练习吧.

先看一下效果图:



一、需求分析

看到效果之后,先来分析一下:

首先是需要一个可以滑动的画轴,并且这个画轴需要一定的滑动空间,有滑动的效果,这个用Scroller帮助完成就可以了.

然后看一下画轴点击移动时候的背景图,是跟随画轴移动,动态改变高度的.这个用一个ImageView来搞定,设置ImageView的scaleType就可以了,不过这个地方有一些小问题,下面会说.

二、具体实现

简单分析完,来实现一下,先来做一下画轴.创建一个ScrollPaintView继承自RelativeLayout,因为需要一定的滑动空间,所以需要是一个ViewGroup.

ScrollPaintView的一些基本属性:

public class ScrollPaintView extends RelativeLayout {
/**
* TAG
*/
private static final String TAG = "ScrollPaintView";
/**
* 默认滚轴高度
*/
private final int DEFAULT_PAINT_SCROLL_HEIGHT = 25;
/**
* 默认滚动的速度
*/
private final int DEFAULT_SCROLL_SPEED = 1000;
/**
* 默认分割点高度
*/
private final int DEFAULT_PARTITION_NODE = 150;
/**
* 默认画轴文字大小
*/
private final int DEFAULT_PAINT_SCROLL_TXT_SIZE = 16;
/**
* Scroller
*/
private Scroller mScroller;
/**
* 滚轴Iv
*/
private ImageView mPaintScrollImageView;
/**
* 滚轴Tv
*/
private TextView mPaintScrollTextView;
/**
* 图画Iv
*/
private ImageView mPaintView;
/**
* 画轴图
*/
private Bitmap mPaintScrollBp;
/**
* 画轴高度
*/
private int mPaintIvHeight;
/**
* 画轴文字
*/
private String mPaintScrollTxt;
/**
* 画轴文字大小
*/
private float mPaintScrollTxtSize;
/**
* 画轴文字颜色
*/
private int mPaintScrollTxtColor;
/**
* 图画开始时的高度
*/
private int mPaintStartHeight;
/**
* 上一次获取的Y
*/
private int mLastY;
/**
* 滚动速度
*/
private int mScrollSpeed;
/**
* 分隔节点
*/
private int partitionNode;
/**
* 是否是向上滚动
*/
private boolean isScrllerTop = false;
/**
* 是否正在点击
*/
private boolean isClick = false;
/**
* 布局参数
*/
private LayoutParams lpp;
/**
* 屏幕高度
*/
private int screenHeight;
/**
* 屏幕宽度
*/
private int screenWidth;
/**
* 回调监听
*/
private ScrollPaintCompleteListener listener;
/**
* 上一次滚动的Y值
*/
private int lastScrollY;

/**
* 构造方法
*/
public ScrollPaintView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 获取属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrollPaintView);
mPaintIvHeight = (int) ta.getDimension(R.styleable.ScrollPaintView_paintScrollHeight, TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, DEFAULT_PAINT_SCROLL_HEIGHT, getResources().getDisplayMetrics()));
mScrollSpeed = ta.getInteger(R.styleable.ScrollPaintView_scrollSpeed, DEFAULT_SCROLL_SPEED);
partitionNode = ta.getInteger(R.styleable.ScrollPaintView_scrollPartitionNode, DEFAULT_PARTITION_NODE);
mPaintScrollBp = drawableToBitamp(ta.getDrawable(R.styleable.ScrollPaintView_paintScrollSrc));
mPaintScrollTxt = ta.getString(R.styleable.ScrollPaintView_paintScrollTxt);
mPaintScrollTxtColor = ta.getColor(R.styleable.ScrollPaintView_paintScrollTxtColor, Color.BLACK);
mPaintScrollTxtSize = px2sp(ta.getDimensionPixelSize(R.styleable.ScrollPaintView_paintScrollTxtSize, DEFAULT_PAINT_SCROLL_TXT_SIZE));
ta.recycle();
}
}


看一下创建画轴:

/**
* 创建滚轴
*/
private void makePaintScroll() {
// 如果已经存在,则不再创建
if (null != mPaintScrollImageView || null != mPaintScrollTextView) {
return;
}
// 创建滚轴
mPaintScrollImageView = new ImageView(getContext());
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.height = mPaintIvHeight;
mPaintScrollImageView.setLayoutParams(lp);
mPaintScrollImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mPaintScrollImageView.setImageBitmap(null == mPaintScrollBp ? makeDefaultScroll() : mPaintScrollBp);
addView(mPaintScrollImageView);
// 创建文字
mPaintScrollTextView = new TextView(getContext());
LayoutParams lpt = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lpt.height = mPaintIvHeight;
mPaintScrollTextView.setLayoutParams(lpt);
mPaintScrollTextView.setText(null == mPaintScrollTxt ? "" : mPaintScrollTxt);
mPaintScrollTextView.setTextSize(mPaintScrollTxtSize);
mPaintScrollTextView.setTextColor(mPaintScrollTxtColor);
mPaintScrollTextView.setGravity(Gravity.CENTER);
addView(mPaintScrollTextView);
}

/**
* 设置默认的滚轴
*
* @return
*/
private Bitmap makeDefaultScroll() {
Bitmap defaultBp = Bitmap.createBitmap(screenWidth, mPaintIvHeight,
Bitmap.Config.ARGB_8888);
//填充颜色
defaultBp.eraseColor(Color.parseColor("#FF0000"));
return defaultBp;

}


创建了一个画轴ImageView和一个文字TextView作为初始的画轴,如果没有传入画轴的图片,则默认去创建一个画轴.不难理解,接着去配合Scroller,让画轴滚动起来.

简单滚动:

/**
* 处理View
*/
private void handleView() {
// 初始化Scroller
mScroller = new Scroller(getContext());
// 画轴点击效果
mPaintScrollImageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
isClick = true;
mLastY = y;
if (!mScroller.isFinished()) { // 如果上次的调用没有执行完就取消。
mScroller.abortAnimation();
}
return true;
case MotionEvent.ACTION_MOVE:
// 移动的距离
int dy = y - mLastY;
mLastY = y;
// 滑动
scrollBy(0, -dy);
return true;
case MotionEvent.ACTION_UP:
mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY(), 1000);
invalidate();
return true;
}
return false;
}
});
}

/**
* 滑动处理
*/
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {  // 计算新位置,并判断上一个滚动是否完成。
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
}


这样滑动处理就做完了,在布局中引用一下,看一下效果

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeeeee"
tools:context="com.example.junweiliu.scrollpaintdemo.MainActivity">
<!--画轴控件-->
<com.example.junweiliu.scrollpaintdemo.widget.ScrollPaintView
android:id="@+id/spv_paint"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:paintScrollHeight="25dp"
app:paintScrollSrc="@mipmap/paint_scroll_img"
app:paintScrollTxt="拉我看看"
app:paintScrollTxtColor="#FF000000"
app:paintScrollTxtSize="16sp"
>
</com.example.junweiliu.scrollpaintdemo.widget.ScrollPaintView>
</RelativeLayout>


效果图:



滚动条基本能用了,接着来设置一个ImageView来配合使用下,先获取到一个ImageView,然后拖动画轴时,来动态改变ImageView的高度,在做这部分内容前,先来考虑下,因为需求需要的是图画整体不会变形,是一点一点拉开的感觉,就像是打开一幅画一样,那么用哪种scaleType能满足呢.试了好多种,来分别看一下:

相关代码:

提供一个设置ImageView的方法

在MotionEvent.ACTION_MOVE:中动态改变ImageView的高度

滑动时动态改变ImageView的高度

/**
* 设置paintView
*
* @param paintView
*/
public void setPaintView(ImageView paintView) {
if (null == paintView) {
Log.e(TAG, "设置的View为空");
return;
}
mPaintView = paintView;
}


MotionEvent.ACTION_MOVE:

// 滑动处理
case MotionEvent.ACTION_MOVE:
...
// 动态改变高度
if (Math.abs(getScrollY()) > 0) {
lpp.height = mPaintStartHeight + Math.abs(getScrollY());
mPaintView.setLayoutParams(lpp);
}


滑动处理:

/**
* 滑动处理
*/
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {  // 计算新位置,并判断上一个滚动是否完成。
// 请求处理点击事件,防止父控件滑动
requestDisallowInterceptTouchEvent(true);
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 重新设置显示的控件高度
if (0 < Math.abs(mScroller.getCurrY())) {
if (!isScrllerTop) {
lpp.height = mPaintStartHeight + Math.abs(mScroller.getCurrY()) + mPaintIvHeight / 2;
} else {
lpp.height = mPaintStartHeight + Math.abs(mScroller.getCurrY()) - mPaintIvHeight / 2;
}
} else {
lpp.height = mPaintStartHeight;
}
mPaintView.setLayoutParams(lpp);
invalidate();
}
}


设置不同scaleType效果,简单试几个效果:

fitXY:



centerCrop:



matrix:



观察一下,好像那个效果都不是很好,不过matrix拉开的效果和预期需要的是一样的,不过用matrix之后,就没有办法设置其他scaleType了,没办法把图片进行缩放了,这肿么办呢,其实很简单,只需要把显示的图片提前进行一下缩放就可以了.

处理图片相关:

/**
* 设置paintView
*
* @param paintView
*/
public void setPaintView(ImageView paintView) {
if (null == paintView) {
Log.e(TAG, "设置的View为空");
return;
}
// 处理图片,对图片按照屏幕宽高比进行缩放
Bitmap bp = drawableToBitamp(paintView.getDrawable());
paintView.setImageBitmap(scaleBitmal(bp));
// 设置缩放形式
paintView.setScaleType(ImageView.ScaleType.MATRIX);
mPaintView = paintView;
}
/**
* drawable转bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitamp(Drawable drawable) {
if (null == drawable) {
return null;
}
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}

/**
* 按照屏幕宽高缩放图片
*
* @param bp
* @return
*/
private Bitmap scaleBitmal(Bitmap bp) {
// 宽度比例
float scaleW = (float) screenWidth / (float) bp.getWidth();
// 高度比例
float scaleH = (float) screenHeight / (float) bp.getHeight();
// 矩阵,用于缩放图片
Matrix matrix = new Matrix();
matrix.postScale(scaleW, scaleH);
// 缩放后的图片
Bitmap scaleBp = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), matrix, true);
return scaleBp;
}


看一下效果:



效果还不错,接下来就是做一下细节上的处理,设置一个临界点,让画轴向上或者向下滚动,设置边界点,让画轴不越界等等.还有一般都是在ScrollView中使用到这个效果,所以要去处理一下事件冲突,当然还有去重写一下onMeasure方法,不然会出现不显示的情况.(相信大家也遇到过ScrollView里边嵌套ListView导致ListView显示不全)这里就不再详细介绍了.直接贴下代码.

三、完整代码

MainActivity:

package com.example.junweiliu.scrollpaintdemo;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.junweiliu.scrollpaintdemo.widget.ScrollPaintView;

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
/**
* 需要显示的IV
*/
private ImageView mPaintIv;
/**
* 画轴
*/
private ScrollPaintView mScrollPaintView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();

}

/**
* 初始化控件
*/
private void initView() {
mPaintIv = (ImageView) findViewById(R.id.iv_paint);
mScrollPaintView = (ScrollPaintView) findViewById(R.id.spv_paint);
mScrollPaintView.setPaintView(mPaintIv);
mPaintIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "功夫!", Toast.LENGTH_SHORT).show();
}
});
mScrollPaintView.setScrollPaintCompleteListener(new ScrollPaintView.ScrollPaintCompleteListener() {
@Override
public void onScrollTouch(TextView tv) {
mPaintIv.setVisibility(View.VISIBLE);
}

@Override
public void onScrollTop(TextView tv) {
//                Log.e(TAG, "收缩了");
tv.setText("拉我看看");
if (View.VISIBLE == mPaintIv.getVisibility()) {
mPaintIv.setVisibility(View.GONE);
}
}

@Override
public void onScrollBottom(TextView tv) {
//                Log.e(TAG, "展开了");
tv.setText("到底了");
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
startActivity(intent);
// 延迟800毫秒重置位置
new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
mScrollPaintView.replaceScroll();
return false;
}
}).sendEmptyMessageDelayed(0, 600);
}

@Override
public void onScrollMove(TextView tv) {
//                Log.e(TAG, "移动了");
tv.setText("请上下拖动");
}
});
}
}


ScrollPaintView:

package com.example.junweiliu.scrollpaintdemo.widget;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;

import com.example.junweiliu.scrollpaintdemo.R;

/**
* Created by junweiliu on 16/12/10.
*/
public class ScrollPaintView extends RelativeLayout {
/**
* TAG
*/
private static final String TAG = "ScrollPaintView";
/**
* 默认滚轴高度
*/
private final int DEFAULT_PAINT_SCROLL_HEIGHT = 25;
/**
* 默认滚动的速度
*/
private final int DEFAULT_SCROLL_SPEED = 1000;
/**
* 默认分割点高度
*/
private final int DEFAULT_PARTITION_NODE = 150;
/**
* 默认画轴文字大小
*/
private final int DEFAULT_PAINT_SCROLL_TXT_SIZE = 16;
/**
* Scroller
*/
private Scroller mScroller;
/**
* 滚轴Iv
*/
private ImageView mPaintScrollImageView;
/**
* 滚轴Tv
*/
private TextView mPaintScrollTextView;
/**
* 图画Iv
*/
private ImageView mPaintView;
/**
* 画轴图
*/
private Bitmap mPaintScrollBp;
/**
* 画轴高度
*/
private int mPaintIvHeight;
/**
* 画轴文字
*/
private String mPaintScrollTxt;
/**
* 画轴文字大小
*/
private float mPaintScrollTxtSize;
/**
* 画轴文字颜色
*/
private int mPaintScrollTxtColor;
/**
* 图画开始时的高度
*/
private int mPaintStartHeight;
/**
* 上一次获取的Y
*/
private int mLastY;
/**
* 滚动速度
*/
private int mScrollSpeed;
/**
* 分隔节点
*/
private int partitionNode;
/**
* 是否是向上滚动
*/
private boolean isScrllerTop = false;
/**
* 是否正在点击
*/
private boolean isClick = false;
/**
* 布局参数
*/
private LayoutParams lpp;
/**
* 屏幕高度
*/
private int screenHeight;
/**
* 屏幕宽度
*/
private int screenWidth;
/**
* 回调监听
*/
private ScrollPaintCompleteListener listener;
/**
* 上一次滚动的Y值
*/
private int lastScrollY;

/**
* 回调接口
*/
public interface ScrollPaintCompleteListener {
/**
* 点击时的回调
*/
public void onScrollTouch(TextView tv);

/**
* 收缩时的回调
*/
public void onScrollTop(TextView tv);

/**
* 展开时的回调
*/
public void onScrollBottom(TextView tv);

/**
* 滚动中的回调
*/
public void onScrollMove(TextView tv);

}

public ScrollPaintView(Context context) {
this(context, null);
}

public ScrollPaintView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ScrollPaintView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 获取属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrollPaintView);
mPaintIvHeight = (int) ta.getDimension(R.styleable.ScrollPaintView_paintScrollHeight, TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, DEFAULT_PAINT_SCROLL_HEIGHT, getResources().getDisplayMetrics()));
mScrollSpeed = ta.getInteger(R.styleable.ScrollPaintView_scrollSpeed, DEFAULT_SCROLL_SPEED);
partitionNode = ta.getInteger(R.styleable.ScrollPaintView_scrollPartitionNode, DEFAULT_PARTITION_NODE);
mPaintScrollBp = drawableToBitamp(ta.getDrawable(R.styleable.ScrollPaintView_paintScrollSrc));
mPaintScrollTxt = ta.getString(R.styleable.ScrollPaintView_paintScrollTxt);
mPaintScrollTxtColor = ta.getColor(R.styleable.ScrollPaintView_paintScrollTxtColor, Color.BLACK);
mPaintScrollTxtSize = px2sp(ta.getDimensionPixelSize(R.styleable.ScrollPaintView_paintScrollTxtSize, DEFAULT_PAINT_SCROLL_TXT_SIZE));
ta.recycle();
init();
makePaintScroll();
handleView();
}

/**
* 设置paintView
*
* @param paintView
*/
public void setPaintView(ImageView paintView) {
if (null == paintView) {
Log.e(TAG, "设置的View为空");
return;
}
// 处理图片,对图片按照屏幕宽高比进行缩放
Bitmap bp = drawableToBitamp(paintView.getDrawable());
paintView.setImageBitmap(scaleBitmal(bp));
// 设置缩放形式
paintView.setScaleType(ImageView.ScaleType.MATRIX);
mPaintView = paintView;
}

/**
* 设置回调
*/
public void setScrollPaintCompleteListener(ScrollPaintCompleteListener listener) {
if (null != listener) {
this.listener = listener;
}
}

/**
* 初始化
*/
private void init() {
mScroller = new Scroller(getContext());
lpp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
// 获取屏幕信息
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay()
.getMetrics(displayMetrics);
// 屏幕高度
screenHeight = displayMetrics.heightPixels;
// 屏幕宽度
screenWidth = displayMetrics.widthPixels;
}

/**
* 创建滚轴
*/
private void makePaintScroll() {
// 如果已经存在,则不再创建
if (null != mPaintScrollImageView || null != mPaintScrollTextView) {
return;
}
// 创建滚轴
mPaintScrollImageView = new ImageView(getContext());
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.height = mPaintIvHeight;
mPaintScrollImageView.setLayoutParams(lp);
mPaintScrollImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mPaintScrollImageView.setImageBitmap(null == mPaintScrollBp ? makeDefaultScroll() : mPaintScrollBp);
addView(mPaintScrollImageView);
// 创建文字
mPaintScrollTextView = new TextView(getContext());
LayoutParams lpt = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lpt.height = mPaintIvHeight;
mPaintScrollTextView.setLayoutParams(lpt);
mPaintScrollTextView.setText(null == mPaintScrollTxt ? "" : mPaintScrollTxt);
mPaintScrollTextView.setTextSize(mPaintScrollTxtSize);
mPaintScrollTextView.setTextColor(mPaintScrollTxtColor);
mPaintScrollTextView.setGravity(Gravity.CENTER);
addView(mPaintScrollTextView);
}

/**
* 测量方法
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (null != mPaintView && getTop() + mPaintIvHeight != mPaintView.getHeight()) {
// 重新设置图画高度
mPaintStartHeight = getTop() + mPaintIvHeight / 2;
lpp.height = mPaintStartHeight;
mPaintView.setLayoutParams(lpp);
}
// 测量状态栏高度
Rect frame = new Rect();
((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
// 高度为屏幕高度减去状态栏高度和top的高度
setMeasuredDimension(screenWidth, screenHeight - getTop() - statusBarHeight);
}

/**
* 处理View
*/
private void handleView() {
mPaintScrollImageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (null == mPaintView) {
Log.e(TAG, "设置的View为空");
return true;
}
// 获取点击的XY坐标
int x = (int) event.getRawX();
int y = (int) event.getRawY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
// 请求处理点击事件
requestDisallowInterceptTouchEvent(true);
isClick = true;
mLastY = y;
if (!mScroller.isFinished()) { // 如果上次的调用没有执行完就取消。
mScroller.abortAnimation();
}
if (null != listener) {
listener.onScrollTouch(mPaintScrollTextView);
}
return true;
}
case MotionEvent.ACTION_MOVE: {
// 移动的距离
int dy = y - mLastY;
mLastY = y;
// 滑动
scrollBy(0, -dy);
//  如果是向上滑动并且是在初始位置,则不去做处理
if (getScrollY() >= 0 && dy <= 0) {
lpp.height = mPaintStartHeight;
mPaintView.setLayoutParams(lpp);
scrollTo(0, 0);
return true;
}
// 如果是向下滑动并且超过屏幕高度,则不去处理
if (Math.abs(getScrollY()) >= getHeight() - mPaintIvHeight && dy >= 0) {
lpp.height = mPaintStartHeight + getHeight() - mPaintIvHeight;
mPaintView.setLayoutParams(lpp);
scrollTo(0, -(getHeight() - mPaintIvHeight));
return true;
}
// 滚动回调
if (null != listener) {
listener.onScrollMove(mPaintScrollTextView);
}
// 重新设置显示的控件高度
if (Math.abs(getScrollY()) > 0) {
lpp.height = mPaintStartHeight + Math.abs(getScrollY());
mPaintView.setLayoutParams(lpp);
}
return true;
}
case MotionEvent.ACTION_UP:
// 恢复事件处理
requestDisallowInterceptTouchEvent(false);
isClick = false;
// 没有发生移动
if (getScrollY() >= 0) {
if (null != listener) {
listener.onScrollTop(mPaintScrollTextView);
}
return true;
}
if (-getScrollY() < partitionNode) {   // 如果小于临界值,则返回起始坐标
// XY都从滑动的距离回去,最后一个参数是多少毫秒内执行完这个动作。
isScrllerTop = true;
mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY(), mScrollSpeed);
} else {    // 如果大于临界值,则展开
isScrllerTop = false;
mScroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -(getHeight() - (-getScrollY()) - mPaintIvHeight), mScrollSpeed);
}
invalidate();
return true;
}
return false;
}
});
}

/**
* 滑动处理
*/
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {  // 计算新位置,并判断上一个滚动是否完成。
// 请求处理点击事件,防止父控件滑动
requestDisallowInterceptTouchEvent(true);
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 重新设置显示的控件高度
if (0 < Math.abs(mScroller.getCurrY())) {
if (!isScrllerTop) {
lpp.height = mPaintStartHeight + Math.abs(mScroller.getCurrY()) + mPaintIvHeight / 2;
} else {
lpp.height = mPaintStartHeight + Math.abs(mScroller.getCurrY()) - mPaintIvHeight / 2;
}
} else {
lpp.height = mPaintStartHeight;
}
mPaintView.setLayoutParams(lpp);
invalidate();
} else {
// 重新设置画图高度,防止高度异常
if (mPaintView.getHeight() > mPaintStartHeight + Math.abs(mScroller.getCurrY()) && !isScrllerTop && mScroller.getStartY() > 0) {
lpp.height = mPaintStartHeight + Math.abs(mScroller.getCurrY());
mPaintView.setLayoutParams(lpp);
}
}
// 防止多次调用
if (lastScrollY != mScroller.getCurrY()) {
// 收缩完成
if (mScroller.getCurrY() >= 0 && !isClick) {
if (null != listener) {
listener.onScrollTop(mPaintScrollTextView);
}
}
// 展开完成
if (-mScroller.getCurrY() >= getHeight() - mPaintIvHeight && !isClick) {
if (null != listener) {
listener.onScrollBottom(mPaintScrollTextView);
}
}
lastScrollY = mScroller.getCurrY();
}
}

/**
* 重置滚动
*/
public void replaceScroll() {
// 重置信息
scrollTo(0, 0);
mScroller.setFinalY(0);
lastScrollY = 0;
lpp.height = mPaintStartHeight;
mPaintView.setLayoutParams(lpp);
if (null != listener) {
listener.onScrollTop(mPaintScrollTextView);
}
}

/**
* drawable转bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitamp(Drawable drawable) {
if (null == drawable) {
return null;
}
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}

/**
* 按照屏幕宽高缩放图片
*
* @param bp
* @return
*/
private Bitmap scaleBitmal(Bitmap bp) {
// 宽度比例
float scaleW = (float) screenWidth / (float) bp.getWidth();
// 高度比例
float scaleH = (float) screenHeight / (float) bp.getHeight();
// 矩阵,用于缩放图片
Matrix matrix = new Matrix();
matrix.postScale(scaleW, scaleH);
// 缩放后的图片
Bitmap scaleBp = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), matrix, true);
return scaleBp;
}

/**
* 设置默认的滚轴
*
* @return
*/
private Bitmap makeDefaultScroll() {
Bitmap defaultBp = Bitmap.createBitmap(screenWidth, mPaintIvHeight,
Bitmap.Config.ARGB_8888);
//填充颜色
defaultBp.eraseColor(Color.parseColor("#FF0000"));
return defaultBp;

}

/**
* 将px值转换为sp值,保证文字大小不变
*/
public int px2sp(float pxValue) {
final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}

}


activity_main:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeeeee"
tools:context="com.example.junweiliu.scrollpaintdemo.MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<!--头部图片部分-->
<ImageView
android:id="@+id/iv_banner"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="fitXY"
android:src="@mipmap/show_banner"/>
<!--中间内容部分-->
<LinearLayout
android:id="@+id/ll_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/iv_banner"
android:layout_marginTop="20dp"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_a"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="艺术片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_b"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="怀旧片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_c"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="科幻片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_d"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="动画片"
android:textColor="#666666"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_sencond"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_first"
android:layout_marginTop="20dp"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout

android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_a"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="艺术片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_b"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="怀旧片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_c"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="科幻片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_d"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="动画片"
android:textColor="#666666"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_threeth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_sencond"
android:layout_marginTop="20dp"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_a"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="艺术片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_b"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="怀旧片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_c"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="科幻片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_d"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="动画片"
android:textColor="#666666"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_fourth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_threeth"
android:layout_marginTop="20dp"
android:orientation="horizontal"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_a"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="艺术片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_b"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="怀旧片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_c"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="科幻片"
android:textColor="#666666"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="80dp"
android:layout_height="120dp"
android:scaleType="fitXY"
android:src="@mipmap/movie_playbill_d"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="动画片"
android:textColor="#666666"/>
</LinearLayout>
</LinearLayout>

<!--需要显示的图-->
<ImageView
android:id="@+id/iv_paint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="@mipmap/show_img"
android:visibility="gone"/>
<!--画轴控件-->
<com.example.junweiliu.scrollpaintdemo.widget.ScrollPaintView
android:id="@+id/spv_paint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/iv_banner"
app:paintScrollHeight="25dp"
app:paintScrollSrc="@mipmap/paint_scroll_img"
app:paintScrollTxt="拉我看看"
app:paintScrollTxtColor="#FF000000"
app:paintScrollTxtSize="16sp"
>
</com.example.junweiliu.scrollpaintdemo.widget.ScrollPaintView>
</RelativeLayout>
</ScrollView>
</RelativeLayout>


attr:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--画轴的高度-->
<attr name="paintScrollHeight" format="dimension"/>
<!--画轴的图片-->
<attr name="paintScrollSrc" format="reference"/>
<!--画轴文字-->
<attr name="paintScrollTxt" format="string"/>
<!--画轴文字颜色-->
<attr name="paintScrollTxtColor" format="color"/>
<!--画轴文字大小-->
<attr name="paintScrollTxtSize" format="dimension"/>
<!--滚动速度-->
<attr name="scrollSpeed" format="integer"/>
<!--分割节点-->
<attr name="scrollPartitionNode" format="integer"/>
<declare-styleable name="ScrollPaintView">
<attr name="paintScrollHeight"/>
<attr name="paintScrollSrc"/>
<attr name="paintScrollTxt"/>
<attr name="paintScrollTxtColor"/>
<attr name="paintScrollTxtSize"/>
<attr name="scrollSpeed"/>
<attr name="scrollPartitionNode"/>
</declare-styleable>
</resources>


四、问题

滚动的时间不宜设置太短,因为动态设置ImageView高度时可能出现绘制速度赶不上滚动的速度,会出现错位,当然时间设置太短,也看不到这种滑动的效果了.暂时想到的做法就是这样,应该还会有更好的方法.

源码地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息