ScrollView與SeekBar綁定實(shí)現(xiàn)滑動(dòng)時(shí)出現(xiàn)小滑塊效果
這是一項(xiàng)挺復(fù)雜的工作
重寫SeekBar
重寫ScroView
主工程
布局
SeekBar樣式修改
綁定SeekBar和ScrollView
監(jiān)聽ScrollView的滑動(dòng)狀態(tài)
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);//旋轉(zhuǎn)
c.translate(0, -getWidth());//旋轉(zhuǎn),這兩行不可去掉
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("也許是在用這種方式告訴我,分開了就不要懷抱希望,現(xiàn)實(shí),夢(mèng)中都不能。\n" +
"\n" +
" 了,那些無(wú)處安放的情感就讓它各自歸位,你別來(lái),");
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);//滑動(dòng)停止后,自動(dòng)隱藏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;
/**
* 使用靜態(tài)方法來(lái)綁定邏輯,代碼可讀性更高。
*/
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) {
//當(dāng)不是用戶操作,也就是ScrollView的滾動(dòng)隱射過(guò)來(lái)時(shí)不執(zhí)行操作
if (!fromUser) {
// seekBar.setProgress();
//將拖動(dòng)的換百分比算成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();
}
/*動(dòng)畫*/
public static final long DEFAULT_TIME_OUT = 10L;
@Override
public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
showScroll();
//用戶拖動(dòng)SeekBar時(shí)不觸發(fā)ScrollView的回調(diào)
if (isUserSeeking) {
return;
}
//計(jì)算當(dāng)前滑動(dòng)位置相對(duì)于整個(gè)范圍的百分比,并映射到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() {
}
/*視圖參數(shù)*/
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;
}
/* 單位轉(zhuǎn)換 */
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數(shù)。你必須先調(diào)用該方法后再使用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數(shù)異常");
}
if (count == 0) {
handleLastMessage(msg);
}
}
/*回調(diào)*/
protected abstract void handleLastMessage(Message msg);
}
上圖

跟著屏幕的滑動(dòng)右邊的小點(diǎn)會(huì)跟著滑動(dòng),點(diǎn)擊滑動(dòng)右邊的小點(diǎn)可以控制屏幕的滑動(dòng),屏幕滑動(dòng)結(jié)束后,小點(diǎn)自動(dòng)隱藏。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android中實(shí)現(xiàn)監(jiān)聽ScrollView滑動(dòng)事件
- Android ScrollView滑動(dòng)實(shí)現(xiàn)仿QQ空間標(biāo)題欄漸變
- Android中ScrollView實(shí)現(xiàn)滑動(dòng)距離監(jiān)聽器的方法
- Android編程開發(fā)ScrollView中ViewPager無(wú)法正?;瑒?dòng)問(wèn)題解決方法
- Android使用自定義控件HorizontalScrollView打造史上最簡(jiǎn)單的側(cè)滑菜單
- Android中ScrollView 滑到頭部或尾部可伸縮放大效果
- Android中Toolbar隨著ScrollView滑動(dòng)透明度漸變效果實(shí)現(xiàn)
- ScrollView嵌套ListView滑動(dòng)沖突的解決方法
- android scrollview 滑動(dòng)到頂端或者指定位置的實(shí)現(xiàn)方法
- Android HorizontalScrollView左右滑動(dòng)效果
相關(guān)文章
Android使用selector修改TextView中字體顏色和背景色的方法
這篇文章主要介紹了Android使用selector修改TextView中字體顏色和背景色的方法,實(shí)例分析了selector方法的相關(guān)使用技巧,需要的朋友可以參考下2016-01-01
android隱式意圖激活自定義界面和系統(tǒng)應(yīng)用界面的實(shí)例
下面小編就為大家?guī)?lái)一篇android隱式意圖激活自定義界面和系統(tǒng)應(yīng)用界面的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
Android為TextView添加字體庫(kù)和設(shè)置描邊的方法
本篇文章主要介紹了Android為TextView添加字體庫(kù)和設(shè)置描邊的方法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09
Android 6.0區(qū)別U盤和SD卡設(shè)備的方法詳解
今天小編就為大家分享一篇Android 6.0區(qū)別U盤和SD卡設(shè)備的方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
詳解Android中使用Notification實(shí)現(xiàn)進(jìn)度通知欄(示例三)
這篇文章主要介紹了詳解Android中使用Notification實(shí)現(xiàn)進(jìn)度通知欄(示例三),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
Android中絕對(duì)音量和相對(duì)音量設(shè)置
大家好,本篇文章主要講的是Android中絕對(duì)音量和相對(duì)音量設(shè)置,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
解決Android SurfaceView繪制觸摸軌跡閃爍問(wèn)題的方法
這篇文章主要為大家詳細(xì)介紹了解決Android SurfaceView繪制觸摸軌跡閃爍問(wèn)題的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03
Kotlin Service服務(wù)組件開發(fā)詳解
這幾天分析了一下的啟動(dòng)過(guò)程,于是乎,今天寫一下Service使用; 給我的感覺(jué)是它并不復(fù)雜,千萬(wàn)不要被一坨一坨的代碼嚇住了,雖然彎彎繞繞不少,重載函數(shù)一個(gè)接著一個(gè),就向走迷宮一樣,但只要抓住主線閱讀,很快就能找到出口2022-12-12

