ScrollView is bound to SeekBar to achieve the effect of small sliders when sliding

It's a complicated job

  • Override SeekBar
  • Override ScroView
  • main project
  • layout
  • SeekBar style modification
  • Bind SeekBar and ScrollView
  • Listen to the sliding state of ScrollView

    1. Rewrite 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. Rewrite 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. Main project

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, the main layout

<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 style

<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. Bind SeekBar and 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. Tools

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. Thread tool

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);
}

Above
Follow the sliding of the screen, the small dot on the right will slide along with it. Click the small dot on the right of the sliding to control the sliding of the screen. After the screen slides over, the small dot will automatically hide.

Follow the sliding of the screen, the small dot on the right will slide along with it. Click the small dot on the right of the sliding to control the sliding of the screen. After the screen slides over, the small dot will automatically hide.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325624095&siteId=291194637