您的位置:首页 > 其它

自定义ScrollView实现图片下拉放大(弹性效果)+ 悬浮框

2017-11-21 09:30 573 查看
效果图:



MyScrollView

package com.bwie.com.wangruixin1509c20171121;

import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.Scroller;

/**
* Created by Wangrx on 2017/11/21.
*/

public class MyScrollView extends ScrollView{
private OnScrollListener onScrollListener;
private int lastScrollY;

private static final int LEN = 0xc8;
private static final int DURATION = 500;
private static final int MAX_DY = 200;
private Scroller mScroller;
TouchTool tool;
int left, top;
float startX, startY, currentX, currentY;
int imageViewH;
int rootW, rootH;
ImageView imageView;
boolean scrollerType;

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

}

public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
}

public MyScrollView(Context context) {
super(context);

}

public void setImageView(ImageView imageView) {
this.imageView = imageView;
}

@Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {

return 0;
}

private int[] li = new int[2];
private int[] li2 = new int[2];
private float lastLy;
private boolean startIsTop = true;

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
super.dispatchTouchEvent(event);
int action = event.getAction();
if (!mScroller.isFinished()) {
return super.onTouchEvent(event);
}
currentX = event.getX();
currentY = event.getY();
imageView.getLocationInWindow(li);
getLocationOnScreen(li2);
imageView.getTop();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (li[1] != li2[1]) {// 判断开始触摸时,imageview和窗口顶部对齐没
startIsTop = false;
}
left = imageView.getLeft();
top = imageView.getBottom();
rootW = getWidth();
rootH = getHeight();
imageViewH = imageView.getHeight();
startX = currentX;
startY = currentY;
tool = new TouchTool(imageView.getLeft(), imageView.getBottom(), imageView.getLeft(),
imageView.getBottom() + LEN);
break;
case MotionEvent.ACTION_MOVE:
if (!startIsTop && li[1] == li2[1]) {
startY = currentY;
startIsTop = true;
}
if (imageView.isShown() && imageView.getTop() >= 0) {
if (tool != null) {
int t = tool.getScrollY(currentY - startY);
if (!scrollerType && currentY < lastLy && imageView.getHeight() > imageViewH) {
scrollTo(0, 0);
imageView.getLocationInWindow(li);
getLocationOnScreen(li2);
android.view.ViewGroup.LayoutParams params = imageView.getLayoutParams();
params.height = t;
imageView.setLayoutParams(params);
if (imageView.getHeight() == imageViewH && li[1] == li2[1]) {
scrollerType = true;
}
if (startIsTop && li[1] != li2[1]) {
startIsTop = false;
}
}
if (t >= top && t <= imageView.getBottom() + LEN && li[1] == li2[1] && currentY > lastLy) {
android.view.ViewGroup.LayoutParams params = imageView.getLayoutParams();
params.height = t;
imageView.setLayoutParams(params);
}
}
scrollerType = false;
}

lastLy = currentY;
break;
case MotionEvent.ACTION_UP:
if (li[1] == li2[1]) {
scrollerType = true;
mScroller.startScroll(imageView.getLeft(), imageView.getBottom(), 0 - imageView.getLeft(),
imageViewH - imageView.getBottom(), DURATION);
invalidate();
}
startIsTop = true;
break;
}

return true;
}

@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
int x = mScroller.getCurrX();
int y = mScroller.getCurrY();
imageView.layout(0, 0, x + imageView.getWidth(), y);
invalidate();
if (!mScroller.isFinished() && scrollerType && y > MAX_DY) {
android.view.ViewGroup.LayoutParams params = imageView.getLayoutParams();
params.height = y;
imageView.setLayoutParams(params);
}
}
}

public class TouchTool {

private int startX, startY;

public TouchTool(int startX, int startY, int endX, int endY) {
super();
this.startX = startX;
this.startY = startY;
}

public int getScrollX(float dx) {
int xx = (int) (startX + dx / 2.5F);
return xx;
}

public int getScrollY(float dy) {
int yy = (int) (startY + dy / 2.5F);
return yy;
}
}

/**
* 设置滚动接口
* @param onScrollListener
*/
public void setOnScrollListener(OnScrollListener onScrollListener){
this.onScrollListener = onScrollListener;
}
/**
* 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中
*/
private Handler handler = new Handler() {

[b]public void handleMessage(android.os.Message msg) {
int scrollY = MyScrollView.this.getScrollY();

//此时的距离和记录下的距离不相等,在隔5毫秒给handler发送消息
if(lastScrollY != scrollY){
lastScrollY = scrollY;
handler.sendMessageDelayed(handler.obtainMessage(), 5);
}
if(onScrollListener != null){
onScrollListener.onScroll(scrollY);
}

}

};

@Override
public boolean onTouchEvent(MotionEvent ev) {
if(onScrollListener != null){
onScrollListener.onScroll(lastScrollY = this.getScrollY());
}
switch(ev.getAction()){
case MotionEvent.ACTION_UP:
handler.sendMessageDelayed(handler.obtainMessage(), 20);
break;
}
return super.onTouchEvent(ev);
}

/**
* 滚动的回调接口
*/
public interface OnScrollListener{
/**
* 回调方法, 返回MyScrollView滑动的Y方向距离
*/
public void onScroll(int scrollY);
}
}

MainActivity

package com.bwie.com.wangruixin1509c20171121;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private ListView listView;
private ImageView imageView;
//    private RelativeLayout relativeLayout;
private RelativeLayout relativeLayout2;
private MyScrollView dampView;

private List<String> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//        initData();

//设置可拉伸的头部ImageView
dampView.setImageView(imageView);

//        //setAdapter
//        listView.setAdapter(new ArrayAdapter<String>(this,
//                android.R.layout.simple_list_item_1, list));

//动态设置ListView单条的高度,解决与scollView的滑动冲突
setListViewHeightBasedOnChildren(listView);

dampView.setOnScrollListener(new MyScrollView.OnScrollListener() {
@Override
public void onScroll(int scrollY) {
if (scrollY >= imageView.getHeight()){
//                    relativeLayout.setVisibility(View.GONE);
relativeLayout2.setVisibility(View.VISIBLE);
}else {
//                    relativeLayout.setVisibility(View.VISIBLE);
relativeLayout2.setVisibility(View.GONE);
}
}
});
}
//    //假数据
//    private void initData() {
//        for (int i = 0; i < 100; i++) {
//            list.add(i, i + "");
//        }
//    }

//查找控件
private void initView() {
dampView = (MyScrollView) findViewById(R.id.dampView);
listView = (ListView) findViewById(R.id.listView);
imageView = (ImageView) findViewById(R.id.imageView);
//        relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
relativeLayout2 = (RelativeLayout) findViewById(R.id.relativeLayout2);

}

//动态设置ListView单条的高度,解决与scollView的滑动冲突
public void setListViewHeightBasedOnChildren(ListView listView) {
// 获取ListView对应的Adapter
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}

int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
// listAdapter.getCount()返回数据项的数目
View listItem = listAdapter.getView(i, null, listView);
// 计算子项View 的宽高
listItem.measure(0, 0);
// 统计所有子项的总高度
totalHeight += listItem.getMeasuredHeight();
}

ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
// listView.getDividerHeight()获取子项间分隔符占用的高度
// params.height最后得到整个ListView完整显示需要的高度
listView.setLayoutParams(params);
}
}

activity_main.xml

<?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"
tools:context="com.bwie.com.wangruixin1509c20171121.MainActivity">

<com.bwie.com.wangruixin1509c20171121.MyScrollView
android:id="@+id/dampView"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@mipmap/i" />

<!--<RelativeLayout-->
<!--android:id="@+id/relativeLayout"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="50dp"-->
<!--android:background="@color/colorAccent">-->

<!--<TextView-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:gravity="center"-->
<!--android:text="固定在顶部" />-->
<!--</RelativeLayout>-->

<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/entry"></ListView>
</LinearLayout>
</com.bwie.com.wangruixin1509c20171121.MyScrollView>

<RelativeLayout
android:id="@+id/relativeLayout2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:visibility="gone">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="固定在顶部" />
</RelativeLayout>

</RelativeLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ScrollView