这个简易 的底部拖拉菜单没什么工作量,这里氷分析了,直接上代码,距离属性没剥离出来,不过很简单,各位大神用到的时候,自己扩展吧

 

代码如下:

 

@interface ViewController ()@property(nonatomic,strong) UIView* bottomView;@property(nonatomic, strong) NSLayoutConstraint *bottomHeightCons;@property(nonatomic,assign) CGPoint startPos;@property(nonatomic,assign) CGPoint endPos;@property(nonatomic,assign) CGPoint originPos;@property(nonatomic,assign) BOOL bIsDirectionDowm;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.        [self initView];    }-(void) initView{    self.bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 100,                                                               self.view.frame.size.width, 300)];    self.bottomView.backgroundColor = [UIColor greenColor];    self.bottomView.translatesAutoresizingMaskIntoConstraints = NO;        UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(100, self.bottomView.frame.size.height - 80, 160, 40)];    label.text = @"底部隐藏菜单";    [self.bottomView addSubview:label];            [self.view addSubview:self.bottomView];        self.originPos = self.bottomView.center;        self.bIsDirectionDowm = false;}-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    UITouch *touch = [touches anyObject];    self.startPos = [touch locationInView:self.view];    }-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{            UITouch *touch = [touches anyObject];    CGPoint curP = [touch locationInView:self.view];        if(curP.y - self.startPos.y <= 0 && curP.y - self.startPos.y >= -200){      //向上滑                if(self.bIsDirectionDowm) return;        self.bottomView.center = CGPointMake(self.bottomView.center.x, self.originPos.y + ( curP.y - self.startPos.y));            }else if(curP.y - self.startPos.y > 0 && curP.y - self.startPos.y <= 100){ //向下滑动            if(!self.bIsDirectionDowm) return;        self.bottomView.center = CGPointMake(self.bottomView.center.x, self.originPos.y - 100 + ( curP.y - self.startPos.y));    }    }//当手指离开屏幕时调用-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{        UITouch *touch = [touches anyObject];    self.endPos = [touch locationInView:self.view];    if(self.endPos.y - self.startPos.y <= 0 && self.endPos.y - self.startPos.y >= -100){  //向上滑动                    [UIView animateWithDuration:0.3 animations:^{                        self.bottomView.center = CGPointMake(self.bottomView.center.x, self.view.frame.size.height - self.bottomView.frame.size.height / 2);            self.bIsDirectionDowm = true;                    }];            }        else if(self.endPos.y - self.startPos.y >= 0 && self.endPos.y - self.startPos.y <= 100){                    [UIView animateWithDuration:0.1 animations:^{                        self.bottomView.center = CGPointMake(self.bottomView.center.x, self.originPos.y);            self.bIsDirectionDowm = false;                    }];            }}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}

 

 

Android 部分:参考:https://www.jb51.net/article/117780.htm

package com.sensetime.armap.widgt;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.Scroller;import androidx.annotation.Nullable;import com.sensetime.armap.R;import com.sensetime.libcenter.utils.LogUtils;/** * Create By 刘铁柱 * Create Date 2019-09-11 * Sensetime@Copyright * Des: 垂直可伸缩菜单 */public class ElasticLayout extends LinearLayout {    LinearLayout bottomBar,bottomContent;    private Scroller mScroller;    public ElasticLayout(Context context) {        super(context);    }    public ElasticLayout(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        mScroller = new Scroller(context);    }    public ElasticLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mScroller = new Scroller(context);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        bottomContent = findViewById(R.id.bottomContent);        bottomBar = findViewById(R.id.bottombar);        findViewById(R.id.bottom_btn).setOnClickListener(new OnClickListener(){            @Override            public void onClick(View view) {                LogUtils.print(48,"");            }        });        findViewById(R.id.bottom_btn2).setOnClickListener(new OnClickListener(){            @Override            public void onClick(View view) {                LogUtils.print(56,"");            }        });    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        bottomBar.layout(0, getMeasuredHeight() - bottomBar.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight());        bottomContent.layout(0, getMeasuredHeight(), getMeasuredWidth(), bottomBar.getBottom() + bottomContent.getMeasuredHeight());    }    float downX,downY;    int scrollOffset;    @Override    public boolean onTouchEvent(MotionEvent event) {        super.onTouchEvent(event);        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                downX = (int) event.getX();                downY = (int) event.getY();                break;            case MotionEvent.ACTION_MOVE:                int endY = (int) event.getY();                int dy = (int) (endY - downY);                int toScroll = getScrollY() - dy;                if(toScroll < 0){                    toScroll = 0;                } else if(toScroll > bottomContent.getMeasuredHeight()){                    toScroll = bottomContent.getMeasuredHeight();                }                scrollTo(0, toScroll);                downY = (int) event.getY();                break;            case MotionEvent.ACTION_UP:                scrollOffset = getScrollY();                if(scrollOffset > bottomContent.getMeasuredHeight() / 2){                    expendBottom();                } else {                    closeBottom();                }                break;        }        return true;    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) { // 计算新位置,并判断上一个滚动是否完成。            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            invalidate();// 再次调用computeScroll。        }    }    private void expendBottom(){        int dy = bottomContent.getMeasuredHeight() - scrollOffset;        mScroller.startScroll(getScrollX(), getScrollY(), 0, dy, 500);        invalidate();    }    private void closeBottom(){        int dy = 0 - scrollOffset;        mScroller.startScroll(getScrollX(), getScrollY(), 0, dy, 500);        invalidate();    }}

 

布局文件:

<?xml version="1.0" encoding="utf-8"?>                        
 

 

 

 

 

更多相关文章

  1. Android动态设置ViewPager是否可手指滑动
  2. [置顶] 【Android】毫无耦合性,一个Item根布局搞定 item侧滑删除
  3. 自定义控件和试图(部分原生api)下拉菜单
  4. android OpenGLES开发第三课 绘制一个可以翻转的Polygon
  5. Android利用ViewPager仿微信主界面-android学习之旅(78)
  6. Android实现ViewPager滑动播放视频,ViewPager+Fragment取消懒加载
  7. Android(安卓)UI控件之Gallery实现循环效果总结
  8. Android的Activity滑动切换动画
  9. Android(安卓)用HorizontalScrollView实现ListView的Item滑动删

随机推荐

  1. android单位转换(TypedValue)
  2. Android(安卓)的消息队列模型
  3. android - 为安全而设计 - 1 - 开发文档
  4. Android(安卓)Add-ons
  5. 分享偶的android秘籍
  6. Android横竖屏切换总结
  7. Android(安卓)Studio Gradle 添加.so 支
  8. Android:ANT打包常见问题简述
  9. Android程序开发初级教程(一) 开始 Hello
  10. 如何启动Android(安卓)SDK 1.5模拟器