ScrollView与SeekBar绑定实现滑动时出现小滑块效果

这是一项挺复杂的工作

重写SeekBar
重写ScroView
主工程
布局
SeekBar样式修改
绑定SeekBar和ScrollView
监听ScrollView的滑动状态

1、重写SeekBar

public class VerticalSeekbar extends SeekBar {
  public VerticalSeekbar(Context context) {
    super(context);
  }
  public VerticalSeekbar(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
  public VerticalSeekbar(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(h, w, oldh, oldw);
  }
  @Override
  public synchronized void setProgress(int progress) // it is necessary for calling setProgress on click of a button
  {
    super.setProgress(progress);
    onSizeChanged(getWidth(), getHeight(), 0, 0);
  }
  @Override
  protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(heightMeasureSpec, widthMeasureSpec);
    setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
  }
  protected void onDraw(Canvas c) {
      c.rotate(90);//旋转
    c.translate(0, -getWidth());//旋转,这两行不可去掉

    super.onDraw(c);
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (!isEnabled()) {
      return false;
    }
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
      case MotionEvent.ACTION_MOVE:
      case MotionEvent.ACTION_UP:
      setProgress((int) (getMax() * event.getY() / getHeight()));
        onSizeChanged(getWidth(), getHeight(), 0, 0);
        break;
   case MotionEvent.ACTION_CANCEL:
        break;
    }
    return true;
  }

}

2、重写SccrollView

public class ObservableScrollView extends ScrollView {
  public ScrollViewListener scrollViewListener = null;
  public ObservableScrollView (Context context) {
    super(context);
  }
  public ObservableScrollView (Context context, AttributeSet attrs,
                 int defStyle) {
    super(context, attrs, defStyle);
  }
  public interface ScrollViewListener {
    void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
  }
  public ObservableScrollView (Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  public void setScrollViewListener(ScrollViewListener scrollViewListener) {
    this.scrollViewListener = scrollViewListener;
  }
  @Override
  public void onScrollChanged(int x, int y, int oldx, int oldy) {
    super.onScrollChanged(x, y, oldx, oldy);
    if (scrollViewListener != null) {
      scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
    }
  }
}

3、主工程

public class Slider_Text extends Activity {
  private TextView textView;
  private Context context=this;
  private Scroller scroller;
  private ScrollBindHelper scrollBindHelper;
  private VerticalSeekbar seekBar;
  private ObservableScrollView scrollView;
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_slider__text);
    scroller=new Scroller(context);
    textView=(TextView)findViewById(R.id.text);
    textView.setText("也许是在用这种方式告诉我,分开了就不要怀抱希望,现实,梦中都不能。\n" +
        "\n" +

        "  了,那些无处安放的情感就让它各自归位,你别来,");
     seekBar = (VerticalSeekbar) findViewById(R.id.seekbar);
     scrollView = (ObservableScrollView) findViewById(R.id.scrollView);
    scrollBindHelper=new ScrollBindHelper(seekBar,scrollView);
    scrollBindHelper.bind(seekBar,scrollView);
    scrollView.setOnTouchListener(new View.OnTouchListener() {
      private int lastY = 0;
      private int touchEventId = -9983761;
      Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
          super.handleMessage(msg);
          View scroller = (View) msg.obj;
          if (msg.what == touchEventId) {
            if (lastY == scroller.getScrollY()) {
              handleStop(scroller);
            } else {
              handler.sendMessageDelayed(handler.obtainMessage(touchEventId, scroller), 5);
              lastY = scroller.getScrollY();
            }
          }
        }
      };

      public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
          handler.sendMessageDelayed(handler.obtainMessage(touchEventId, v), 5);
        }
        return false;
      }
      //处理真正的事件
      private void handleStop(Object view) {
        ScrollView scroller = (ScrollView) view;
        int scrollY = scroller.getScrollY();
        System.out.println("scrollY"+scrollY);
        seekBar.setVisibility(View.GONE);//滑动停止后,自动隐藏seekbar
      }
    });

  }
}

4、主布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal"
  tools:context="io.dcloud.H5B79C397.testActivity.Slider_Text">
  <io.dcloud.H5B79C397.view.ObservableScrollView
    android:id="@+id/scrollView"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="15">
    <TextView
      android:id="@+id/text"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="asdfasdfasdfff" />
  </io.dcloud.H5B79C397.view.ObservableScrollView >
  <io.dcloud.H5B79C397.view.VerticalSeekbar
    android:id="@+id/seekbar"
    android:layout_width="0dp"
    android:visibility="gone"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:progressDrawable="@drawable/seek"
    android:thumbTint="@color/green" />
</LinearLayout>

5、SeekBar样式

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@android:id/background">
    <shape>
      <corners android:radius="5dp"/>
      <solid android:color="#FFFFFF"/>
    </shape>
  </item>
  <item android:id="@android:id/secondaryProgress">
    <clip>
      <shape>
        <corners android:radius="5dp"/>
        <solid android:color="#FFFFFF"/>
      </shape>
    </clip>
  </item>
  <item android:id="@android:id/progress">
    <clip>
      <shape>
        <corners android:radius="5dp"/>
        <solid android:color="#FFFFFF" />
      </shape>
    </clip>
  </item>
</layer-list>

6、绑定SeekBar和ScrollView

public class ScrollBindHelper implements SeekBar.OnSeekBarChangeListener,ObservableScrollView.ScrollViewListener{
  private final VerticalSeekbar seekBar;
  private final ObservableScrollView scrollView;
  private final View scrollContent;
  /**
   * 使用静态方法来绑定逻辑,代码可读性更高。
   */
  public ScrollBindHelper(VerticalSeekbar seekBar, ObservableScrollView scrollView) {
    this.seekBar = seekBar;
    this.scrollView = scrollView;
    this.scrollContent = scrollView.getChildAt(0);
    // System.out.println("scrollContent------->"+scrollView.getChildAt(0));
  }
  /*继承*/
  private boolean isUserSeeking;
  private int getContentRange() {
    seekBar.setMax(scrollContent.getHeight() - scrollView.getHeight());
    int Range=scrollView.getScrollY();
    //System.out.println("content----->"+Range);
    return Range;
  }
  private int getScrollRange() {
    System.out.println(scrollContent.getHeight() - scrollView.getHeight());
    return scrollContent.getHeight() - scrollView.getHeight();
}
  public ScrollBindHelper bind(VerticalSeekbar seekBar, ObservableScrollView scrollView) {
    //初始化工具类
    ViewUtil.init(seekBar.getContext().getApplicationContext());
    ScrollBindHelper helper = new ScrollBindHelper(seekBar, scrollView);
    seekBar.setOnSeekBarChangeListener(helper);
    scrollView.setScrollViewListener(helper);
    return helper;
  }

@Override
  public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    //当不是用户操作,也就是ScrollView的滚动隐射过来时不执行操作
    if (!fromUser) {
      // seekBar.setProgress();
      //将拖动的换百分比算成Y值,并映射到SrollView上。
      int range=getContentRange();
      scrollView.scrollTo(0, progress);
     //  System.out.println("scroll----"+progress);
    }
}
  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
    isUserSeeking = true;
    handler.clearAll();
  }
  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
    isUserSeeking = false;
    handler.reset();
  }
  /*动画*/
  public static final long DEFAULT_TIME_OUT = 10L;
  @Override
  public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
    showScroll();
    //用户拖动SeekBar时不触发ScrollView的回调
    if (isUserSeeking) {
      return;
    }

    //计算当前滑动位置相对于整个范围的百分比,并映射到SeekBar上
    int range = getContentRange();
    seekBar.setProgress(range != 0 ? range : 0);
    //System.out.println("seekBar------"+ range);
  }
  private static class VisibleHandler extends LastMsgHandler {
    private ScrollBindHelper helper;
    public VisibleHandler(ScrollBindHelper helper) {
      this.helper = helper;
    }
    public void reset() {
      sendMsgDelayed(DEFAULT_TIME_OUT);
    }
    @Override
    protected void handleLastMessage(Message msg) {
      helper.hideScroll();
    }
  }
  private VisibleHandler handler = new VisibleHandler(this);

  private void hideScroll() {
    seekBar.setVisibility(View.GONE);
  }
  private void showScroll() {
    seekBar.setVisibility(View.VISIBLE);
  }
}

7、工具类

public class ViewUtil {
  private ViewUtil() {
  }

  /*视图参数*/
  private static float density;
  private static float scaledDensity;
  private static int widthPixels;
  private static int heightPixels;

  private static boolean isInit = false;

  private static void confirmInit() {
    if (!isInit) {
      throw new IllegalStateException("ViewUtil还未初始化");
    }
  }
  public static void init(Context context) {
    if (isInit) {
      return;
    }

    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    density = displayMetrics.density;
    scaledDensity = displayMetrics.scaledDensity;
    widthPixels = displayMetrics.widthPixels;
    heightPixels = displayMetrics.heightPixels;
    isInit = true;
  }

  public static float getDisplayMetricsDensity() {
    confirmInit();
    return density;
  }

  public static float getDisplayMetricsScaledDensity() {
    confirmInit();
    return scaledDensity;
  }

  public static int getScreenWidthPx() {
    confirmInit();
    return widthPixels;
  }

  public static int getScreenHeightPx() {
    confirmInit();
    return heightPixels;
  }

  /* 单位转换 */

  public static int dpToPx(float dpValue) {
    confirmInit();
    return (int) (dpValue * getDisplayMetricsDensity() + 0.5F);
  }

  public static int pxToDp(float pxValue) {
    confirmInit();
    return (int) (pxValue / getDisplayMetricsDensity() + 0.5F);
  }

  public static int pxToSp(float pxValue) {
    confirmInit();
    return (int) (pxValue / getDisplayMetricsScaledDensity() + 0.5f);
  }

  public static int spToPx(float spValue) {
    confirmInit();
    return (int) (spValue * getDisplayMetricsScaledDensity() + 0.5f);
  }
}

8、线程工具

public abstract class LastMsgHandler extends android.os.Handler {
  private int count = 0;

  /**
   * 增加Count数。你必须先调用该方法后再使用sendMessageXXX
   */
  public synchronized final void increaseCount() {
    count++;
  }

  public final void sendMsg() {
    sendMsgDelayed(0);
  }

  public final void sendMsgDelayed(long delay) {
    increaseCount();
    if (delay <= 0) {
      sendEmptyMessage(0);
    } else {
      sendEmptyMessageDelayed(0, delay);
    }
  }

  public synchronized final void clearAll() {
    count = 0;
    removeCallbacksAndMessages(null);
  }

  @Override
  public synchronized final void handleMessage(Message msg) {
    super.handleMessage(msg);
    count--;
    if (count < 0) {
      throw new IllegalStateException("count数异常");
    }

    if (count == 0) {
      handleLastMessage(msg);
    }
  }

  /*回调*/

  protected abstract void handleLastMessage(Message msg);
}

上图

跟着屏幕的滑动右边的小点会跟着滑动,点击滑动右边的小点可以控制屏幕的滑动,屏幕滑动结束后,小点自动隐藏。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android HorizontalScrollView左右滑动效果

    本文实例为大家分享了Android HorizontalScrollView左右滑动的具体代码,供大家参考,具体内容如下 效果图 一.什么是HorizontalScrollView HorizontalScrollView实际上是一个FrameLayout ,这意味着你只能在它下面放置一个子控件 ,这个子控件可以包含很多数据内容.有可能这个子控件本身就是一个布局控件,可以包含非常多的其他用来展示数据的控件.这个布局控件一般使用的是一个水平布局的LinearLayout.TextView也是一个可

  • Android中实现监听ScrollView滑动事件

    时候我们需要监听ScroView的滑动情况,比如滑动了多少距离,是否滑到布局的顶部或者底部.可惜的是SDK并没有相应的方法,不过倒是提供了一个 复制代码 代码如下: protected void onScrollChanged(int x, int y, int oldx, int oldy) 方法,显然这个方法是不能被外界调用的,因此就需要把它暴露出去,方便使用.解决方式就是写一个接口, 复制代码 代码如下: package com.example.demo1;    public inter

  • Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法

    本文实例讲述了Android编程开发ScrollView中ViewPager无法正常滑动问题解决方法.分享给大家供大家参考,具体如下: 这里主要介绍如何解决ViewPager在ScrollView中滑动经常失效.无法正常滑动问题. 解决方法只需要在接近水平滚动时ScrollView不处理事件而交由其子View(即这里的ViewPager)处理即可,重写ScrollView的onInterceptTouchEvent函数,如下: package cc.newnews.view; import an

  • Android中Toolbar随着ScrollView滑动透明度渐变效果实现

    Android中Toolbar随着ScrollView滑动透明度渐变效果实现 一.思路:监听ScrollView的滑动事件 不断的修改Toolbar的透明度 二.注意 1.ScrollView 6.0以前没有scrollView.setOnScrollChangeListener(l)方法  所以要自定义ScrollView 在onScrollChanged()中监听 2.ScrollView 6.0(23)以前没有scrollView.setOnScrollChangeListener()方法

  • Android ScrollView滑动实现仿QQ空间标题栏渐变

    今天来研究的是ScrollView-滚动视图,滚动视图又分横向滚动视图(HorizontalScrollView)和纵向滚动视图(ScrollView),今天主要研究纵向的.相信大家在开发中经常用到,ScrollView的功能已经很强大了,但是仍然满足不了我们脑洞大开的UI设计师们,所以我们要自定义-本篇文章主要讲监听ScrollView的滑动实现仿QQ空间标题栏渐变,先看一下效果图: 好了我们切入主题. 有可能你不知道的那些ScrollView属性  •android:scrollbars 设

  • ScrollView嵌套ListView滑动冲突的解决方法

    ScrollView和ListView这两个控件想必大家都不会陌生,但是这两者嵌套使用的时候就会出现麻烦.比如,我们如果想在ListView下面添加其他的布局或者控件,然后想让它们作为一个整体都可以滑动的话,最常想到的就是用一个ScrollView把它们包裹起来.想法似乎很美好,但是现实就有点残酷了.我们可以写一个小例子体验一下. 首先创建一个Activity,在它的布局文件上放置一个ListView: <?xml version="1.0" encoding="utf

  • Android中ScrollView实现滑动距离监听器的方法

    前言 众所周知ScrollView是我们经常使用的一个UI控件,也许你在使用ScrollView的过程中会发现,当你想监听ScrollView滑动的距离时却没有合适的监听器!当然在API 23中有setOnScrollChangeListener(View.OnScrollChangeListener l)可以使用,但是并不兼容低版本的API.那怎么办呢?只好重写ScrollView来实现对滑动距离的监听了. 话不多说,直接上代码: public class MyScrollView exten

  • Android中ScrollView 滑到头部或尾部可伸缩放大效果

    最近做项目,想要这么一个效果,就是ScrollView 滑动到顶部,当不能在滑动的时候,图片可以下拉放大,松开又恢复.滑到底部没有内容的时候,也有伸缩效果,先看看效果图吧. 就是如上图这么个效果.系统提供的ScrollView 是不能做到这个效果的,所以需要自己自定义,网上找了一些资料.也参考了下其他人的做法.自己也整合了一下.希望对大家有所帮助. 核心的控件就是下面的这段代码: package com.kokjuis.travel.customView; import android.anim

  • android scrollview 滑动到顶端或者指定位置的实现方法

    在Android开发中很多时候会遇到一屏显示不下所有内容的现象,那大家也知道这个时候肯定会想到用scrollview来进行滚屏显示. 这个时候由于某些需求,会要求在最开始显示scrollview的时候就定位到某一处,这篇就是来讲这个的哈- 首先,scrollView.scrollTo( x, y );这个方法是能对滚动条进行定位的,这个大家都知道. But,貌似很多时候这个方法的调用没有什么效果呀-- 上面所说的调用scrollTo方法看上去好像并没有起到对滚动条进行定位的效果,其实是因为我们是

  • Android使用自定义控件HorizontalScrollView打造史上最简单的侧滑菜单

    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的改变leftMargin等实现:多少都有点复杂,完成以后还需要对滑动冲突等进行处理~~今天给大家带来一个简单的实现,史上最简单有点夸张,但是的确是我目前遇到过的最简单的一种实现~~~ 1.原理分析 既然是侧滑,无非就是在巴掌大的屏幕,塞入大概两巴掌大的布局,需要滑动可以出现另一个,既然这样,大家为啥不考虑使用Android

随机推荐