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 全然使用定义好的布局. 因此不能简单象其他好窗体进行自定,如今我们须要加 一个自己定义标题 ...
随机推荐
- system_call中断处理过程
张雨梅 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000 1.给menuos添加命令 改 ...
- iOS - QRCode 二维码
1.QRCode 在 iOS7 以前,在 iOS 中实现二维码和条形码扫描,我们所知的有,两大开源组件 ZBar 与 ZXing. 这两大组件我们都有用过,这里总结下各自的缺点: 1.ZBar 在扫描 ...
- 修改CMD字符编码
1.参考网址: 1.1.http://blog.useasp.net/archive/2012/04/24/how_to_use_UTF8_encoding_in_Windows_CMD.aspx 1 ...
- WPF感悟
WPF感悟 UI层与逻辑层要尽可能地剥离(解耦). Routed Event和Command比Event的耦合度要低. UI层与逻辑层的“血管”是数据关联(Data Binding). 尽量不要试图通 ...
- 误删除libc.so.6 恢复
一.我是怎样一步一步毁掉系统的 最近在centos 7上进行开发.由于需要使用高版本linux内核的特性,需要将linux内核升级.按照教程:centos 7升级内核 进行升级的时候发现在安装elre ...
- settings.php rwx
440/400 https://www.drupal.org/node/137702 You must understand the meaning of XYZ chmod from file at ...
- ActiveReports 11 新特性速递
又到了一年一度,翘首期盼的ActiveReports11 即将发布,ActiveReports 10 表控件横空出世,成为中国式复杂报表的救星后,ActiveReports11 又会有哪些令人惊奇的新 ...
- Android studio下gradle Robolectric单元测试配置
android studio下gradle Robolectric单元测试配置 1.Robolectric Robolectric是一个基于junit之上的单元测试框架.它并不依赖于Android提供 ...
- 基于jstree的 对混乱的 命名系统进行归类的 计算机软件
本人现在就职于一家加拿大东部餐饮连锁公司的IT部门,公司旗下有4个品牌,280多家餐厅. 所有的餐厅都使用maitred 的pos软件来处理收银结账. 公司总部使用business object 对m ...
- 安装MySQL(简便)
1.在本地虚拟机上上传mysql的5个安装包 2.查看opt目录下是否有这5个安装包 yum install /var/opt/mysql-community-* -y //安装MySQL syste ...