web-dev-qa-db-ja.com

androidでスライドを解除してボタンをロック解除する方法

こんにちは私はIOSの「ロックを解除するスライド」ボタンとして機能するボタンが欲しい

要するに、クリック効果はないが、ドラッグ中に左から右にスライドでき、ドラッグ完了時にクリックと見なされるボタンが必要です。

可能であればサンプルコードを提案してください。

ありがとう!

17

まず最初に、@ matthiasの回答に感謝します。次のシークバーをカスタマイズして使用しました。

 <SeekBar
        Android:id="@+id/myseek"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:clickable="false"
        Android:max="100"
        Android:progressDrawable="@Android:color/transparent"
        Android:thumb="@drawable/ic_launcher" />

およびJavaコード

sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

            if (seekBar.getProgress() > 95) {

            } else {

                seekBar.setThumb(getResources().getDrawable(R.drawable.ic_launcher));
            }

        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {


        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            if(progress>95){
                seekBar.setThumb(getResources().getDrawable(R.drawable.load_img1));
            }

        }
    });
30

私はJignesh Ansodariyaが投稿した例から始めましたが、Aerrowが指摘するように、ユーザーはSeekBarの任意の場所をクリックしてロックを解除できます。スライドボタンがあることのポイントは、偶発的なクリックを無視する必要があることです。私の解決策は、次のようにSeekBarのサブクラスを作成することでした。

public class SlideButton extends SeekBar {

    private Drawable thumb;
    private SlideButtonListener listener;

    public SlideButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setThumb(Drawable thumb) {
        super.setThumb(thumb);
        this.thumb = thumb;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (thumb.getBounds().contains((int) event.getX(), (int) event.getY())) {
                super.onTouchEvent(event);
            } else
                return false;
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getProgress() > 70)
                handleSlide();

            setProgress(0);
        } else
            super.onTouchEvent(event);

        return true;
    }

    private void handleSlide() {
        listener.handleSlide();
    }

    public void setSlideButtonListener(SlideButtonListener listener) {
        this.listener = listener;
    }   
}

public interface SlideButtonListener {
    public void handleSlide();
}

XML:

        <package.SlideButton
            Android:id="@+id/unlockButton"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:clickable="false"
            Android:max="100"
            Android:progressDrawable="@Android:color/transparent"
            Android:thumb="@drawable/button_lock" >
        </package.SlideButton>

そして最後に私のアクティビティ内のコード:

    ((SlideButton) findViewById(R.id.unlockButton)).setSlideButtonListener(new SlideButtonListener() {  
        @Override
        public void handleSlide() {
            unlockScreen();
        }
    });
20
Oskar Lundgren

あなたのためにトリックを行うためのいくつかの良いライブラリがあります。ライブラリを使用してこれを実行することが問題ではない場合は、これを試すことを検討してください。

https://github.com/cortinico/slidetoact

enter image description here

幸せなコーディング.. !! :)

3
Midhu

このライブラリを使用して、ロック解除をすばやく簡単にカスタマイズできます。

https://github.com/cheekiat/SlideToUnlock

このコードをxmlで使用する

 <cheekiat.slideview.SlideView
        Android:id="@+id/slide_view"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:slideBackground="@drawable/orangesquarebutton"
        app:slideSrc="@drawable/slide_image"
        app:slideText="Slide to unlock"
        app:slideTextColor="#ffffff"
        app:slideTextSize="10dp" />

スライドして画面のロックを解除

1
kiat hee

Androidは Switch ウィジェットを提供しており、これはslide to unlockに似ています。ただし、少しカスタマイズする必要があります。クリック時の変更を無効にします。

0

オスカーの回答から始めて(貢献に感謝します)スライドボタン(水平および垂直)を管理するための簡単なサンプルプロジェクトを作成します。 https://github.com/rcaboni/AndroidSlideButton

スクリーンショットの場合: https://raw.githubusercontent.com/rcaboni/AndroidSlideButton/master/screenshot.jpg

これが主な方法です:

public boolean onTouchEvent(MotionEvent event) {
    if (!isEnabled()) {
        return false;
    }
    if (orientation == ORIENTATION_HORIZONTAL) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int x= (int) event.getX();
            int y= (int) event.getY();
            if (thumb.getBounds().contains((int) event.getX(), (int) event.getY())) {
                super.onTouchEvent(event);
            } else
                return false;
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getProgress() > 70)
                handleSlide();

            setProgress(0);
        } else
            super.onTouchEvent(event);
    }else{
        int i=0;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    int x= (int) event.getX();
                    int y= (int) event.getY();
                    if (!thumb.getBounds().contains((int) event.getY(), (int) event.getX())) {
                        return false;
                    }
                }
            case MotionEvent.ACTION_MOVE:
                i=getMax() - (int) (getMax() * event.getY() / getHeight());
                setProgress(100 - i);
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;
            case MotionEvent.ACTION_UP:
                i=getMax() - (int) (getMax() * event.getY() / getHeight());
                if (i < 30) {
                    handleSlide();
                }
                setProgress(0);
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
    }
    return true;
}

垂直ボタンのXML:

<RelativeLayout
    Android:layout_width="75dp"
    Android:layout_height="130dp"
    Android:background="@drawable/slide_background_green"
    Android:id="@+id/lSlideButtonV"
    Android:layout_below="@+id/lSlideButton"
    Android:layout_marginTop="50dp">
    <TextView
        Android:layout_width="20dp"
        Android:layout_height="match_parent"
        Android:text="SOS"
        Android:id="@+id/tvSlideActionV"
        Android:gravity="center|bottom"
        Android:layout_alignParentRight="false"
        Android:layout_alignParentEnd="false"
        Android:layout_alignParentLeft="false"
        Android:layout_alignParentStart="false"
        Android:textSize="20dp"
        Android:textColor="@Android:color/white"
        Android:layout_alignParentTop="false"
        Android:layout_centerHorizontal="true"
        Android:layout_alignParentBottom="false"
        Android:layout_marginBottom="15dp" />
    <it.aldea.Android.widget.SlideButton
        Android:id="@+id/unlockButtonV"
        Android:layout_width="match_parent"
        Android:layout_height="150dp"
        Android:clickable="false"
        Android:max="100"
        slideButton:orientation="vertical"
        Android:progressDrawable="@Android:color/transparent"
        Android:thumb="@drawable/slide_track_red"
        Android:indeterminate="false"
        Android:layout_marginRight="5dp"
        Android:layout_marginTop="20dp"
        Android:layout_centerInParent="true"
        Android:layout_marginBottom="10dp"
        Android:thumbOffset="-2dp">
    </it.aldea.Android.widget.SlideButton>

</RelativeLayout>

2つのビュー(TextViewとSlideButton)からレイアウトに構成されているため、実際の完全なウィジェットではありませんが、内部にテキストがあるスライドボタンの簡単に構成可能なソリューションです。これが誰かに役立つことを願っています。

0
iLoveCode

なんらかの理由で、タッチアクションを無効にできなかったため、偶発的なタップが引き続き発生する可能性があります
私はこのソリューションを思いつきました、それは基本的に変更イベントごとに10を超える値で進行状況を変更することを許可しません

int unlockLastSeekVal = 0;
// there are skips btwn changes, use value greater than 1
// 10 is great for seekbars with 100 values
int unlockSeekSensitivity = 10;
// final stage to "unlock"; 0.9 => 90%
Double unlockFinalStage = 0.9;
//...........
unlock.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if (fromUser){
            if (Math.abs(unlockLastSeekVal - progress) > unlockSeekSensitivity){
                // too much delta, revert to last value
                seekBar.setProgress(unlockLastSeekVal);
            }else{
                unlockLastSeekVal = progress;
            }
        }
    }

    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    public void onStopTrackingTouch(SeekBar seekBar) {
        if (seekBar.getProgress() > seekBar.getMax() * unlockFinalStage){
            DoYourThing();
        }
        unlockLastSeekVal = 0;
        seekBar.setProgress(0);         
    }
});
0
UnLoCo

おそらく非常に遅いかもしれませんが、この目的のために小さなライブラリを作成しました。 xmlからボタンの動作をスワイプしてカスタマイズできます。 スライドボタン

基本的には、onTouch()イベントのオーバーライドと、受け取った座標に応じた変更を行います。その後、必要に応じて背景を設定し、テキストをカスタマイズするのは簡単です。

0
Shitij Goyal

私は以下を願っていますそして、仕事です、

    public class UnlockSliderView extends FrameLayout {
    @BindView(R2.id.tv_unlock_slider)
    TextView tvUnlockSlider;

    @BindView(R2.id.iv_circle_slide)
    ImageView ivCircleSlide;

    private View parentCircle;

    private float xOrigin = 0;
    private float xOriginCircle = 0;
    private boolean circleTouched = false;

    public UnlockSliderView(Context context) {
        super(context);
        init();
    }

    public UnlockSliderView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public UnlockSliderView(Context context, AttributeSet attr, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.layout_unlock_slider_view, this);
        ButterKnife.bind(this);

        parentCircle = (View) ivCircleSlide.getParent();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            eventActionDown(event);
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            eventActionMove(event);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            unlockFinish();
        }
        return true;
    }

    private void eventActionDown(MotionEvent event) {
        if ((event.getX() >= ivCircleSlide.getX() && event.getX() <= ivCircleSlide.getX() + ivCircleSlide.getWidth())
                && (event.getY() >= ivCircleSlide.getY() && event.getY() <= ivCircleSlide.getY() + ivCircleSlide.getHeight())) {
            xOrigin = event.getX();
            xOriginCircle = ivCircleSlide.getX();
            circleTouched = true;
        } else {
            circleTouched = false;
        }
    }

    private void eventActionMove(MotionEvent event) {
        if (circleTouched) {
            float newXCircle = xOriginCircle + (event.getX() - xOrigin);
            newXCircle = (newXCircle < xOriginCircle) ? xOriginCircle : newXCircle;
            newXCircle = (newXCircle > parentCircle.getWidth() - ivCircleSlide.getWidth() - xOriginCircle) ? parentCircle.getWidth() - ivCircleSlide.getWidth() - xOriginCircle : newXCircle;
            float alpha = 1 - ((newXCircle - xOriginCircle) / (parentCircle.getWidth() - ivCircleSlide.getWidth() - (xOriginCircle * 2)));
            tvUnlockSlider.setAlpha(alpha);
            ivCircleSlide.setX(newXCircle);
            if (newXCircle == parentCircle.getWidth() - ivCircleSlide.getWidth() - xOriginCircle) {
                unlockFinish();
                if (mListener != null) mListener.onUnlock();
            }
        }
    }

    private void unlockFinish() {
        if (circleTouched) {
            ivCircleSlide.animate().x(xOriginCircle).setDuration(400).start();
            tvUnlockSlider.animate().alpha(1).setDuration(400).start();
            circleTouched = false;
        }
    }




   and the xml is,

  <?xml version="1.0" encoding="utf-8"?>
   <FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="fill_parent"
    Android:layout_height="@dimen/unlock_slider_height"
    Android:layout_margin="@dimen/default_padding"
    Android:background="@drawable/btn_slider_back"
    Android:gravity="center"
    Android:orientation="vertical"
    Android:padding="4dp">

    <TextView
        Android:id="@+id/tv_unlock_slider"
        style="@style/prelogin_slider"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:layout_marginLeft="@dimen/unlock_slider_handle_size"
        Android:layout_marginStart="@dimen/unlock_slider_handle_size"
        Android:text="@string/logon_to_mobile_banking" />

    <ImageView

        Android:id="@+id/iv_circle_slide"
        Android:layout_width="@dimen/unlock_slider_handle_size"
        Android:layout_height="@dimen/unlock_slider_handle_size"
        Android:scaleType="fitCenter"
        Android:src="@drawable/btn_slider_handle"
        tools:ignore="ContentDescription" />

</FrameLayout>
0
Vinoj Vetha

@Oskar Lundgrenの回答に感謝します。いくつかのことを更新しました。誰かがkotlinで同じことをしたいと思っている場合は。ここにあります

SlideToConfirm

class SlideToConfirm : SeekBar, SeekBar.OnSeekBarChangeListener {

    private lateinit var listener: SlideButtonListener

    // To prevent the thumb to going out of track
    private val maxProgress = 91
    private val minProgress = 9

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init()
    }

    fun init() {
        setDrawables()
        setProperties()
        setOnSeekBarChangeListener(this)
    }

    private fun setDrawables() {
        thumb = ContextCompat.getDrawable(context, R.drawable.slider_thumb)
        progressDrawable = ContextCompat.getDrawable(context, R.drawable.slider_progress_drawable)
    }

    private fun setProperties() {
        isClickable = false
        splitTrack = false
        setPadding(0, 0, 0, 0)
        progress = minProgress
    }

    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        if (progress < minProgress) {
            this.progress = minProgress
        }
        if (progress > maxProgress) {
            this.progress = maxProgress
        }
    }

    override fun onStartTrackingTouch(seekBar: SeekBar?) {}

    override fun onStopTrackingTouch(seekBar: SeekBar?) {}

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event!!.action == MotionEvent.ACTION_DOWN) {
            if (thumb.bounds.contains(event.x.toInt(), event.y.toInt())) {
                super.onTouchEvent(event)
            } else
                return false
        } else if (event.action == MotionEvent.ACTION_UP) {
            if (progress > 70) {
                handleSlide()
                progress = maxProgress
            } else {
                progress = minProgress
            }
        } else {
            super.onTouchEvent(event)
        }
        return true
    }

    fun setOnSlideListener(listener: SlideButtonListener) {
        this.listener = listener
    }

    private fun handleSlide() {
        listener.handleSlide()
    }

    interface SlideButtonListener {
        fun handleSlide()
    }
}

親指

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item>
        <shape Android:shape="oval">
            <solid Android:color="@color/cyan" />
            <corners Android:radius="8dp" />
            <size
                Android:width="50dp"
                Android:height="50dp" />
        </shape>
    </item>
    <item Android:drawable="@drawable/ic_arrow_forward_white" />
</layer-list>

進捗状況

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:shape="rectangle">
    <corners Android:radius="35dp" />
    <size
        Android:width="100dp"
        Android:height="50dp" />
    <stroke
        Android:width="1dp"
        Android:color="@color/errorRed" />
    <solid Android:color="@Android:color/white" />
</shape>
0
OhhhThatVarun

通常のSeekBarを再構築して、必要な処理を実行できます。

と:

  • 開始点(20)
  • 交差線(90)
  • そして自動リセット。

    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){Integer point = 0; Integer startPoint = 0; boolean started = true;

        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean wasUserInput) {
            point = i;
    
            if (started && i > 0 && wasUserInput) {
                startPoint = new Integer(i);
                started = false;
            }
        }
    
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }
    
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (point > 90 && startPoint < 20) { // slided to the right correctly.
                // TODO::
    
            } else { // reset.
                resetSeekBar(seekBar, point);
            }
    
            startPoint = 0;
            started = true;
        }
    });
    

そして:

/**
 * Resetting the seekbar, on point at a time.
 * @param seekBar                           Reference to the seekbar made smaller.
 * @param oldPoint                          The point where the dot is atm.
 */
private void resetSeekBar(final SeekBar seekBar, final int oldPoint) {
    if (oldPoint > 0) {
        final int newPoint = oldPoint -1;
        seekBar.setProgress(newPoint);

        timer.schedule(new TimerTask() {
            final SeekBar seekBar = seekBarBid;
            @Override
            public void run() {
                resetSeekBar(seekBar, newPoint);
            }
        }, 3);

    } else {
        seekBar.setProgress(oldPoint);
    }
}