android 有弹性的ScrollView 简单实现,与处理ScrollView和ListView,GridView之间的冲突
处理ScrollView和ListView,GridView之间的冲突,
最好的办法就是继承这两个类,重写他们的onMeasure方法即可:
ListView:
import android.widget.ListView; /**
* ScrollView中嵌入ListView,让ListView全显示出来
* @author John
*
*/
public class MyListView extends ListView{ public MyListView(android.content.Context context,android.util.AttributeSet attrs){
super(context, attrs);
} /**
* 设置不滚动
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec); } }
GridView:
import android.widget.GridView; public class MyGridView extends GridView {
public MyGridView(android.content.Context context,
android.util.AttributeSet attrs) {
super(context, attrs);
} /**
* 设置不滚动
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec); } }
如果是ListView中嵌套GridView也可以用这个办法。简单实用的处理了这个冲突。
下面是重写ScrollView,实现有弹性的ScrollView
/**
* 有弹性的ScrollView
* 实现下拉弹回和上拉弹回
* @author John
*/
public class OwnScroview extends ScrollView { private static final String TAG = "ElasticScrollView"; //移动因子, 是一个百分比, 比如手指移动了100px, 那么View就只移动20px
//目的是达到一个延迟的效果
private static final float MOVE_FACTOR = 0.4f; //松开手指后, 界面回到正常位置需要的动画时间
private static final int ANIM_TIME = 300; //ScrollView的子View, 也是ScrollView的唯一一个子View
private View contentView; //手指按下时的Y值, 用于在移动时计算移动距离
//如果按下时不能上拉和下拉, 会在手指移动时更新为当前手指的Y值
private float startY; //用于记录正常的布局位置
private Rect originalRect = new Rect(); //手指按下时记录是否可以继续下拉
private boolean canPullDown = false; //手指按下时记录是否可以继续上拉
private boolean canPullUp = false; //在手指滑动的过程中记录是否移动了布局
private boolean isMoved = false; public OwnScroview(Context context) {
super(context);
} public OwnScroview(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
contentView = getChildAt(0);
}
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b); if(contentView == null) return; //ScrollView中的唯一子控件的位置信息, 这个位置信息在整个控件的生命周期中保持不变
originalRect.set(contentView.getLeft(), contentView.getTop(), contentView
.getRight(), contentView.getBottom());
} /**
* 在触摸事件中, 处理上拉和下拉的逻辑
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) { if (contentView == null) {
return super.dispatchTouchEvent(ev);
} int action = ev.getAction(); switch (action) {
case MotionEvent.ACTION_DOWN: //判断是否可以上拉和下拉
canPullDown = isCanPullDown();
canPullUp = isCanPullUp(); //记录按下时的Y值
startY = ev.getY();
break; case MotionEvent.ACTION_UP: if(!isMoved) break; //如果没有移动布局, 则跳过执行 // 开启动画
TranslateAnimation anim = new TranslateAnimation(0, 0, contentView.getTop(),
originalRect.top);
anim.setDuration(ANIM_TIME); contentView.startAnimation(anim); // 设置回到正常的布局位置
contentView.layout(originalRect.left, originalRect.top,
originalRect.right, originalRect.bottom); //将标志位设回false
canPullDown = false;
canPullUp = false;
isMoved = false; break;
case MotionEvent.ACTION_MOVE: //在移动的过程中, 既没有滚动到可以上拉的程度, 也没有滚动到可以下拉的程度
if(!canPullDown && !canPullUp) {
startY = ev.getY();
canPullDown = isCanPullDown();
canPullUp = isCanPullUp(); break;
} //计算手指移动的距离
float nowY = ev.getY();
int deltaY = (int) (nowY - startY); //是否应该移动布局
boolean shouldMove =
(canPullDown && deltaY > 0) //可以下拉, 并且手指向下移动
|| (canPullUp && deltaY< 0) //可以上拉, 并且手指向上移动
|| (canPullUp && canPullDown); //既可以上拉也可以下拉(这种情况出现在ScrollView包裹的控件比ScrollView还小) if(shouldMove){
//计算偏移量
int offset = (int)(deltaY * MOVE_FACTOR); //随着手指的移动而移动布局
contentView.layout(originalRect.left, originalRect.top + offset,
originalRect.right, originalRect.bottom + offset); isMoved = true; //记录移动了布局
} break;
default:
break;
} return super.dispatchTouchEvent(ev);
} /**
* 判断是否滚动到顶部
*/
private boolean isCanPullDown() {
return getScrollY() == 0 ||
contentView.getHeight() < getHeight() + getScrollY();
} /**
* 判断是否滚动到底部
*/
private boolean isCanPullUp() {
return contentView.getHeight() <= getHeight() + getScrollY();
} }
然后再xml中用上就行了。
android 有弹性的ScrollView 简单实现,与处理ScrollView和ListView,GridView之间的冲突的更多相关文章
- ScrollView listView gridView 之间的冲突问题
在ScrollView中的listView gridView添加适配器之后添加//设置gridView整体的高度 public void setListViewHeightBasedOnChildre ...
- android scrollview 简单的使用
以前写的Scrollview ,通常都是与Listview结合使用,不过因复杂可能新手不太懂,网上有许多文章,这里就不贴那个了DEMO了. 写了个简单的供大家参考:这样比较好理解(需要复杂的可以Q我 ...
- Android ScrollView嵌套HorizontalScrollView 滑动问题 ScrollView包括GridView显示问题
今天项目使用到ScrollView嵌套HorizontalScrollView,ScrollView里包括GridView,发现几个问题非常经典.在此记录: 问题1.ScrollView嵌套Horiz ...
- Xamarin.Android之引导页的简单制作
0x01 前言 对于现在大部分的APP,第一次打开刚安装或更新安装的APP都会有几个引导界面,通常这几个引导页是告诉用户 APP有些什么功能或者修改了什么bug.新增了什么功能等等等. 下面就用Xam ...
- Android Activity的生命周期简单总结
Android Activity的生命周期简单总结 这里的内容参考官方的文档,这篇文章的目的不是去总结Activity是如何启动,如何创造,以及暂停和销毁的,而是从实际开发中分析在Activity各个 ...
- Android 设计随便说说之简单实践(合理组合)
上一篇(Android 设计随便说说之简单实践(模块划分))例举了应用商店设计来说明怎么做模块划分.模块划分主要依赖于第一是业务需求,具体是怎么样的业务.应用商店则包括两个业务,就是向用户展示appl ...
- 怎样在Android实现桌面清理内存简单Widget小控件
怎样在Android实现桌面清理内存简单Widget小控件 我们常常会看到类似于360.金山手机卫士一类的软件会带一个widget小控件,显示在桌面上,上面会显示现有内存大小,然后会带一个按键功能来一 ...
- Android BLE与终端通信(一)——Android Bluetooth基础API以及简单使用获取本地蓝牙名称地址
Android BLE与终端通信(一)--Android Bluetooth基础API以及简单使用获取本地蓝牙名称地址 Hello,工作需要,也必须开始向BLE方向学习了,公司的核心技术就是BLE终端 ...
- Android peferenceActivity 自己定义标题简单方法
Android peferenceActivity 自己定义标题简单方法 peferenceActivity 全然使用定义好的布局. 因此不能简单象其他好窗体进行自定,如今我们须要加 一个自己定义标题 ...
随机推荐
- php : Warning: strftime(): It is not safe to rely on the system's timezone settings.
使用 Smarty 的时候出现这种警告: Warning: strftime(): It is not safe to rely on the system's timezone settings. ...
- 绝对炫的3D幻灯片-SLICEBOX
绝对炫的3D幻灯片-SLICEBOX http://www.jq22.com/jquery-info31
- display inline-block 垂直居中
table td:after {display:inline-block;width:0;height:100%;vertical-align:middle;content:'';}
- Ubuntu下安装Koala
1.下载koala ,官方网址 目前官方链接的到百度云上的包好像有问题,不能安装,这里分享下 https://yunpan.cn/ckAF4L3TR4kKG (提取码:179a) 2.执行 $ sud ...
- iOS - AppStores App 上架
前言 1.准备 开发者账号 完工的项目 2.上架步骤 1) 创建 App ID 2) 创建证书请求文件(CSR文件) 3) 创建发布证书(CER) 4) 创建 Provisioning Profile ...
- static 作用
静态,定义静态变量或者静态函数的时候使用该关键字. 被定义为static的函数,可以不需要new一个新类别而直接调用 比如Math类里有一个,public static sub()方法,那么你可以直接 ...
- Python_Day11_同步IO和异步IO
同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. ...
- jQuery 日常工作集中问题
1.siblings()方法:获得匹配元素中每个元素的同胞(除了自己外的其他同级元素) 导航栏选择效果 点击“华东地区”,其他同级元素灰色背景以及下拉菜单消失,当前元素有灰色背景以及下拉菜单.再次点击 ...
- (转)px、em、rem的区别和使用
国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem(国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位),那么三者有什么区别,又各自有什么优劣呢? 一.px特点 1. IE ...
- 一道Integer面试题引发的对Integer的探究
面试题: //在jdk1.5的环境下,有如下4条语句: Integer i01 = 59; int i02 = 59; Integer i03 =Integer.valueOf(59); Intege ...