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中用上就行了。

  • 相关阅读:
    循环神经网络(LSTM和GRU)(1)
    threading包的例子和queue包的例子
    xgboost调参
    理解 Python 中的 *args 和 **kwargs
    TFRecords文件的生成和读取(1)
    tensorflow函数介绍(4)
    python其他篇(1)
    python实现Restful服务(基于flask)(2)
    开源多线程性能测试工具-sysbench
    MySQL 8.0.0 版本发布,亮点都在这了!
  • 原文地址:https://www.cnblogs.com/android-host/p/5360218.html
Copyright © 2011-2022 走看看