zoukankan      html  css  js  c++  java
  • 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中用上就行了。

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    《EffectiveJava中文第二版》 高清PDF下载
    《MoreEffectiveC++中文版》 pdf 下载
    《啊哈c语言》 高清 PDF 下载
  • 原文地址:https://www.cnblogs.com/android-host/p/5360218.html
Copyright © 2011-2022 走看看