ScrollView與SeekBar綁定實現(xiàn)滑動時出現(xiàn)小滑塊效果
這是一項挺復雜的工作
重寫SeekBar
重寫ScroView
主工程
布局
SeekBar樣式修改
綁定SeekBar和ScrollView
監(jiān)聽ScrollView的滑動狀態(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)實,夢中都不能。\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;
/**
* 使用靜態(tà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) {
//當不是用戶操作,也就是ScrollView的滾動隱射過來時不執(zhí)行操作
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時不觸發(fā)ScrollView的回調(diào)
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() {
}
/*視圖參數(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);
}
上圖

跟著屏幕的滑動右邊的小點會跟著滑動,點擊滑動右邊的小點可以控制屏幕的滑動,屏幕滑動結(jié)束后,小點自動隱藏。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android中實現(xiàn)監(jiān)聽ScrollView滑動事件
- Android ScrollView滑動實現(xiàn)仿QQ空間標題欄漸變
- Android中ScrollView實現(xiàn)滑動距離監(jiān)聽器的方法
- Android編程開發(fā)ScrollView中ViewPager無法正?;瑒訂栴}解決方法
- Android使用自定義控件HorizontalScrollView打造史上最簡單的側(cè)滑菜單
- Android中ScrollView 滑到頭部或尾部可伸縮放大效果
- Android中Toolbar隨著ScrollView滑動透明度漸變效果實現(xiàn)
- ScrollView嵌套ListView滑動沖突的解決方法
- android scrollview 滑動到頂端或者指定位置的實現(xiàn)方法
- Android HorizontalScrollView左右滑動效果
相關(guān)文章
Android使用selector修改TextView中字體顏色和背景色的方法
這篇文章主要介紹了Android使用selector修改TextView中字體顏色和背景色的方法,實例分析了selector方法的相關(guān)使用技巧,需要的朋友可以參考下2016-01-01
android隱式意圖激活自定義界面和系統(tǒng)應用界面的實例
下面小編就為大家?guī)硪黄猘ndroid隱式意圖激活自定義界面和系統(tǒng)應用界面的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06
Android 6.0區(qū)別U盤和SD卡設備的方法詳解
今天小編就為大家分享一篇Android 6.0區(qū)別U盤和SD卡設備的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
詳解Android中使用Notification實現(xiàn)進度通知欄(示例三)
這篇文章主要介紹了詳解Android中使用Notification實現(xiàn)進度通知欄(示例三),具有一定的參考價值,有興趣的可以了解一下。2016-12-12
解決Android SurfaceView繪制觸摸軌跡閃爍問題的方法
這篇文章主要為大家詳細介紹了解決Android SurfaceView繪制觸摸軌跡閃爍問題的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-03-03

