Android自定義垂直拖動seekbar進(jìn)度條
Android自帶的SeekBar是水平的,要垂直的,必須自己寫一個類,繼承SeekBar。
一個簡單的垂直SeekBar的例子:
(但是它其實(shí)是存在一些問題的。不過要是滿足基本需要還是可以湊合的)
package com.example.helloverticalseekbar; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.SeekBar; public class VerticalSeekBar extends SeekBar { public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public VerticalSeekBar(Context context, AttributeSet attrs) { super(context, attrs); } public VerticalSeekBar(Context context) { super(context); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(h, w, oldh, oldw); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } @Override protected synchronized void onDraw(Canvas canvas) { canvas.rotate(-90); canvas.translate(-getHeight(), 0); super.onDraw(canvas); } @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(getMax() - (int) (getMax() * event.getY() / getHeight())); onSizeChanged(getWidth(), getHeight(), 0, 0); break; case MotionEvent.ACTION_CANCEL: break; } return true; } }
Demo中加上一個水平SeekBar作為對比,代碼如下:
Activity:
HelloSeekBarActivity
package com.example.helloverticalseekbar; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; import android.widget.SeekBar; import android.widget.TextView; import android.widget.SeekBar.OnSeekBarChangeListener; public class HelloSeekBarActivity extends Activity { private SeekBar horiSeekBar = null; private TextView horiText = null; private VerticalSeekBar verticalSeekBar = null; private TextView verticalText = null; @Override protected void onCreate(Bundle savedInstanceState) { Log.d(AppConstants.LOG_TAG, "onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_hello_seek_bar); horiSeekBar = (SeekBar) findViewById(R.id.horiSeekBar); horiText = (TextView)findViewById(R.id.horiText); horiSeekBar.setOnSeekBarChangeListener(horiSeekBarListener); verticalSeekBar = (VerticalSeekBar)findViewById(R.id.verticalSeekBar); verticalText = (TextView)findViewById(R.id.verticalText); verticalSeekBar.setOnSeekBarChangeListener(verticalSeekBarChangeListener); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.hello_seek_bar, menu); return true; } private OnSeekBarChangeListener horiSeekBarListener = new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Log.d(AppConstants.LOG_TAG, "Horizontal SeekBar --> onProgressChanged"); horiText.setText(Integer.toString(progress)); } }; private OnSeekBarChangeListener verticalSeekBarChangeListener = new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Log.d(AppConstants.LOG_TAG, "Vertical SeekBar --> onProgressChanged"); verticalText.setText(Integer.toString(progress)); } }; }
布局:
activity_hello_seek_bar.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".HelloSeekBarActivity" > <TextView android:id="@+id/myTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="@string/hello_world" /> <SeekBar android:id="@+id/horiSeekBar" android:layout_width="match_parent" android:layout_height="20dp" android:layout_below="@id/myTextView" /> <TextView android:id="@+id/horiText" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_below="@id/horiSeekBar" android:text="horizontal" /> <com.example.helloverticalseekbar.VerticalSeekBar android:id="@+id/verticalSeekBar" android:layout_width="wrap_content" android:layout_height="200dp" android:layout_below="@id/horiText" /> <TextView android:id="@+id/verticalText" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_below="@id/verticalSeekBar" android:text="vertical" /> </RelativeLayout>
運(yùn)行截圖:
一個改進(jìn)版的SeekBar
package com.example.helloverticalseekbarv2; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.SeekBar; public class VerticalSeekBar extends SeekBar { private boolean mIsDragging; private float mTouchDownY; private int mScaledTouchSlop; private boolean isInScrollingContainer = false; public boolean isInScrollingContainer() { return isInScrollingContainer; } public void setInScrollingContainer(boolean isInScrollingContainer) { this.isInScrollingContainer = isInScrollingContainer; } /** * On touch, this offset plus the scaled value from the position of the * touch will form the progress value. Usually 0. */ float mTouchProgressOffset; public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } public VerticalSeekBar(Context context, AttributeSet attrs) { super(context, attrs); } public VerticalSeekBar(Context context) { super(context); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(h, w, oldh, oldw); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } @Override protected synchronized void onDraw(Canvas canvas) { canvas.rotate(-90); canvas.translate(-getHeight(), 0); super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (isInScrollingContainer()) { mTouchDownY = event.getY(); } else { setPressed(true); invalidate(); onStartTrackingTouch(); trackTouchEvent(event); attemptClaimDrag(); onSizeChanged(getWidth(), getHeight(), 0, 0); } break; case MotionEvent.ACTION_MOVE: if (mIsDragging) { trackTouchEvent(event); } else { final float y = event.getY(); if (Math.abs(y - mTouchDownY) > mScaledTouchSlop) { setPressed(true); invalidate(); onStartTrackingTouch(); trackTouchEvent(event); attemptClaimDrag(); } } onSizeChanged(getWidth(), getHeight(), 0, 0); break; case MotionEvent.ACTION_UP: if (mIsDragging) { trackTouchEvent(event); onStopTrackingTouch(); setPressed(false); } else { // Touch up when we never crossed the touch slop threshold // should // be interpreted as a tap-seek to that location. onStartTrackingTouch(); trackTouchEvent(event); onStopTrackingTouch(); } onSizeChanged(getWidth(), getHeight(), 0, 0); // ProgressBar doesn't know to repaint the thumb drawable // in its inactive state when the touch stops (because the // value has not apparently changed) invalidate(); break; } return true; } private void trackTouchEvent(MotionEvent event) { final int height = getHeight(); final int top = getPaddingTop(); final int bottom = getPaddingBottom(); final int available = height - top - bottom; int y = (int) event.getY(); float scale; float progress = 0; // 下面是最小值 if (y > height - bottom) { scale = 0.0f; } else if (y < top) { scale = 1.0f; } else { scale = (float) (available - y + top) / (float) available; progress = mTouchProgressOffset; } final int max = getMax(); progress += scale * max; setProgress((int) progress); } /** * This is called when the user has started touching this widget. */ void onStartTrackingTouch() { mIsDragging = true; } /** * This is called when the user either releases his touch or the touch is * canceled. */ void onStopTrackingTouch() { mIsDragging = false; } private void attemptClaimDrag() { ViewParent p = getParent(); if (p != null) { p.requestDisallowInterceptTouchEvent(true); } } @Override public synchronized void setProgress(int progress) { super.setProgress(progress); onSizeChanged(getWidth(), getHeight(), 0, 0); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android 添加隨意拖動的桌面懸浮窗口
- Android 可拖動的seekbar自定義進(jìn)度值
- Android 仿淘寶、京東商品詳情頁向上拖動查看圖文詳情控件DEMO詳解
- android 應(yīng)用內(nèi)部懸浮可拖動按鈕簡單實(shí)現(xiàn)代碼
- android Matrix實(shí)現(xiàn)圖片隨意放大縮小或拖動
- Android 實(shí)現(xiàn)可任意拖動的懸浮窗功能(類似懸浮球)
- Android實(shí)現(xiàn)ImageView圖片縮放和拖動
- Android實(shí)現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實(shí)例demo)
- Android編程之控件可拖動的實(shí)現(xiàn)方法
- Android自定義View實(shí)現(xiàn)拖動自動吸邊效果
相關(guān)文章
android圖像繪制(四)自定義一個SurfaceView控件
自定義控件(類似按鈕等)的使用,自定義一個SurfaceView。如某一塊的動態(tài)圖(自定義相應(yīng)),或者類似UC瀏覽器下面的工具欄,感興趣的朋友可以了解下2013-01-01android實(shí)現(xiàn)音樂跳動效果的示例代碼
這篇文章主要介紹了android實(shí)現(xiàn)音樂跳動效果的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Android自定義View系列之Path繪制仿支付寶支付成功動畫
這篇文章主要為大家詳細(xì)介紹了Android自定義View系列之Path繪制仿支付寶支付成功動畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12仿網(wǎng)易新聞客戶端頭條ViewPager嵌套實(shí)例
正確使用requestDisallowInterceptTouchEvent(boolean flag)方法,下面為大家介紹下外層ViewPager布局的實(shí)例,感興趣的朋友可以參考下哈2013-06-06Android 自定義標(biāo)題欄 顯示網(wǎng)頁加載進(jìn)度的方法實(shí)例
Android 自定義標(biāo)題欄 顯示網(wǎng)頁加載進(jìn)度的方法實(shí)例,需要的朋友可以參考一下2013-06-06Android實(shí)現(xiàn)淘寶商品列表切換效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)淘寶商品列表切換效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Android Retrofit文件下載進(jìn)度顯示問題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android Retrofit文件下載進(jìn)度顯示問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01