可横向或部分横向滑动的列表实现

      先看下效果:


 

 

    首先需要构造一个header部分,header部分分为固定header和滑动header,滑动header采用横向scrollview实现:

private void bindHeader(){
    headerLiearLayout = new LinearLayout(context);
headerLiearLayout.setOrientation(HORIZONTAL);
LinearLayout.LayoutParams params = new LayoutParams(dp2px(75),rowHeight);
params.gravity = Gravity.CENTER;
    for (String str:fixedList){
        TextView tv = new TextView(context);
tv.setText(str);
tv.setTextColor(Color.WHITE);
tv.setGravity(Gravity.CENTER);
headerLiearLayout.addView(tv,params);
}
    rightHeader = new LinearLayout(context);
    for(String str:movedList){
        TextView tv = new TextView(context);
tv.setText(str);
tv.setTextColor(Color.WHITE);
tv.setGravity(Gravity.CENTER);
rightHeader.addView(tv,params);
}
    headerLiearLayout.addView(rightHeader);
addView(headerLiearLayout);
}

 

下面列表部分使用listview:

private void buildListView(){
    movableLayout = new LinearLayout(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
listView = new ListView(context);
movableLayout.setLayoutParams(params);
listView.setBackgroundColor(0xff9f9f9f);
listView.setLayoutParams(params);
movableLayout.addView(listView,params);
addView(movableLayout,params);
}

 

 

布局模式完成,现在关键是如何实现横向滑动,且只是部分内容横向滑动。

由于我们自己需要主动去滑动,因此我们需要监听滑动事件,并能区分是横向动作还是竖直动作,如果是竖直动作的话只需要交给listview实现就可以了,横向则需要我们自己主动去滑动部分子view,以下为事件的拦截及处理机制:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    if(action == MotionEvent.ACTION_MOVE &&
            (mTouchState != TOUCH_STATE_RESET)){
        return true;
}
    int x = (int) ev.getX();
    int y = (int) ev.getY();
    switch (action){
        case MotionEvent.ACTION_DOWN:
            lastX = x;
lastY = y;
mTouchState = scroller.isFinished()?TOUCH_STATE_RESET:TOUCH_STATE_SCRONING;
            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = (int)Math.abs(lastX - x);
            int deltaY = (int)Math.abs(lastY - y);
            if(deltaX > deltaY ){
                mTouchState = TOUCH_STATE_SCRONING;
}
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            mTouchState = TOUCH_STATE_RESET;
            break;
}
    return mTouchState != TOUCH_STATE_RESET;

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    int action = event.getAction();
    int x = (int)event.getX();

    if (velocityTracker == null) {
        velocityTracker = VelocityTracker.obtain();
}
    velocityTracker.addMovement(event);
    switch (action){
        case MotionEvent.ACTION_DOWN:
            lastX = x;
            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = (int)(lastX - x);
lastX = x;
            if(scroller != null && rightHeader != null){
                scroller.startScroll((int)(rightHeader.getScrollX()),0,deltaX,0,0);
invalidate();
}
            break;
        case MotionEvent.ACTION_UP:
            final VelocityTracker vt = velocityTracker;
vt.computeCurrentVelocity(1000);
            int velocityX = (int) vt.getXVelocity();
            int max = rightHeader.getChildAt(0).getWidth() * rightHeader.getChildCount()
                    - rightHeader.getWidth();
scroller.fling(rightHeader.getScrollX(),0,-velocityX,0,0,max,0,0);
invalidate();
            if (velocityTracker != null) {
                velocityTracker.recycle();
velocityTracker = null;
}
            mTouchState = TOUCH_STATE_RESET;
            break;
        case MotionEvent.ACTION_CANCEL:
            mTouchState = TOUCH_STATE_RESET;
            break;
}
    return true;
}

 

    Scroll 是一个滚动控制器,在这里需要用它来实现横向滑动。注意startscroll和fling函数,看名字就知道了这里不多述,重要的一点是调用了该函数后,主动刷新view会条用completscroll函数(不明白的可以查看view的刷新机制),在这个函数中是实现真正的滑动部分:

@Override
public void computeScroll() {
    if(scroller.computeScrollOffset()){
        int scrollX = scroller.getCurrX();
        final int maxX = rightHeader.getChildAt(0).getWidth() * rightHeader.getChildCount() - rightHeader.getWidth();
scrollX = Math.max(0,scrollX);
scrollX = Math.min(maxX,scrollX);
rightHeader.scrollTo(scrollX,0);
scrollChildTo(scrollX);
}
}

 

 

在scrollchildTo函数中完成对listview中各个child的部分view的横向滑动:

protected void scrollChildTo(int mScrollX)
{
    if(listView != null)
    {
        View temp = null;
        int nChildCount = listView.getChildCount();
        for(int i = 0; i < nChildCount; i++)
        {
            temp = listView.getChildAt(i);

            int size =  ((ViewGroup) temp).getChildCount();
            for(int j = 0;j < size;j ++){
                View item = ((ViewGroup) temp).getChildAt(j);
                if(item instanceof LinearLayout) {
                    item.scrollTo(mScrollX, 0);
}

            }

        }
    }
}

 

这里的item布局可以看出,横向滚动部分使用linearlayout部分包裹,因此只需要让该view滚动即可.

最后就是适配器的处理了,基本上adapter跟普通的一样,不过有一点需要注意的是view的重用机制会造成最后一条滚动异常,我们需要加上一段矫正代码:

private void adjustMoved(View view) {
    View moveView = (View) view.findViewById(R.id.moveLayout);
    int moveX1 = moveView.getScrollX();
    int moveX2 = ajustView.getScrollX();
    if(moveX1 != moveX2){
        moveView.scrollTo(ajustView.getScrollX(),0);
}
}

 

基本实现基本完成了,剩下的事情就是填充数据展示之类的。

抱歉,公司不能传代码,如果有需要的可以给我留言,我重新写一个完整的。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现移动端touch事件的横向滑动列表效果可以使用原生的JavaScript和CSS3来实现。 首先,我们需要在HTML中创建一个容器元素,用来包含列表项。容器元素需要设置overflow-x属性为scroll,使得内容超出容器范围时可以滚动。 ```html <div class="container"> <ul class="list"> <li>项1</li> <li>项2</li> <li>项3</li> <li>项4</li> <li>项5</li> </ul> </div> ``` 然后,在CSS中,我们需要设置容器元素和列表项的样式,以及使用CSS3的transition属性来实现平滑的过渡效果。 ```css .container { width: 100%; overflow-x: scroll; -webkit-overflow-scrolling: touch; /* 添加iOS滚动效果 */ } .list { display: flex; flex-wrap: nowrap; /* 设置列表项不换行 */ transition: transform 0.3s ease; /* 添加平滑的过渡效果 */ } .list li { width: 100px; height: 100px; margin-right: 10px; background-color: #ccc; } ``` 最后,在JavaScript中,我们需要监听容器元素的touchstart、touchmove和touchend事件,计算滑动距离并通过改变列表项的transform属性来实现横向滑动效果。 ```javascript const container = document.querySelector('.container'); const list = document.querySelector('.list'); let isDragging = false; let startPosition = 0; let currentTranslate = 0; let prevTranslate = 0; let animationId = 0; container.addEventListener('touchstart', touchStart); container.addEventListener('touchmove', touchMove); container.addEventListener('touchend', touchEnd); container.addEventListener('touchcancel', touchEnd); function touchStart(event) { if (event.target.classList.contains('list')) { isDragging = true; startPosition = event.touches[0].clientX; animationId = requestAnimationFrame(updateAnimation); container.classList.add('grabbing'); } } function touchMove(event) { if (isDragging) { const currentPosition = event.touches[0].clientX; currentTranslate = prevTranslate + currentPosition - startPosition; } } function touchEnd() { isDragging = false; cancelAnimationFrame(animationId); prevTranslate = currentTranslate; container.classList.remove('grabbing'); } function updateAnimation() { list.style.transform = `translateX(${currentTranslate}px)`; animationId = requestAnimationFrame(updateAnimation); } ``` 通过以上代码,我们就成功地实现了移动端touch事件的横向滑动列表效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值