Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle sticky mode #49

Open
shayanpourvatan opened this issue Oct 22, 2017 · 7 comments
Open

handle sticky mode #49

shayanpourvatan opened this issue Oct 22, 2017 · 7 comments

Comments

@shayanpourvatan
Copy link

I've created following class to handle sticky mode for wheelView.

use this if you need sticky mode for your wheelView.

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.lukedeighton.wheelview.WheelView;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by shayan on 10/20/17.
 */
public class StickyWheelView extends WheelView implements WheelView.OnWheelAngleChangeListener {


    Timer timer;
    TimerTask timerTask;

    boolean handleSticky;
    Handler uiHandler;

    OnWheelAngleChangeListener onWheelAngleChangeListener;

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


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

    public StickyWheelView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        super.setOnWheelAngleChangeListener(this);
        uiHandler = new Handler(Looper.getMainLooper());
    }

    @Override
    public void setOnWheelAngleChangeListener(OnWheelAngleChangeListener listener) {
        this.onWheelAngleChangeListener = listener;
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            handleSticky = false;
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            handleSticky = true;
            onWheelAngleChange(getAngle());
        }

        return super.onTouchEvent(event);
    }

    @Override
    public void onWheelAngleChange(float angle) {
        timer = invalidateTimerAndCreateNew(timer, timerTask);
        timerTask = new TimerTask() {
            @Override
            public void run() {
                goToNearestFixItem();
            }
        };

        timer.schedule(timerTask, 100);

        // call listener if is not null
        if (onWheelAngleChangeListener != null) {
            onWheelAngleChangeListener.onWheelAngleChange(angle);
        }
    }

    private void goToNearestFixItem() {


        if (!handleSticky) {
            return;
        }
        // getAngle is wide range, we map it too 0 - 360
        float correctAngle = Math.abs(getAngle()) % 360;

        // each item angle
        float itemAngle = 360 / getWheelItemCount();

        // item is currently sticky.
        if (correctAngle % itemAngle == 0) {
            return;
        }

        int power = Math.abs((int) (getAngle() / 360));

        float nextAngle = ((int) (correctAngle / itemAngle) + 1) * itemAngle + (360 * power);
        float preAngle = ((int) (correctAngle / itemAngle)) * itemAngle + (360 * power);
        int sign = getAngle() < 0 ? -1 : 1;


        if (correctAngle % itemAngle > itemAngle / 2) {
            goToAngleWithAnimation(nextAngle * sign);
        } else {
            goToAngleWithAnimation(preAngle * sign);
        }
    }

    private float temporaryFinalAngel;

    private void goToAngleWithAnimation(float angle) {
        temporaryFinalAngel = angle;

        final boolean increase;
        increase = getAngle() <= angle;

        uiHandler.post(new Runnable() {
            @Override
            public void run() {

                if (temporaryFinalAngel == getAngle()) {
                    return;
                }

                // user changed angle again, don't set angle again
                if (!handleSticky) {
                    return;
                }

                float nextAngle;
                if (increase) {
                    nextAngle = Math.min(getAngle() + 3, temporaryFinalAngel);
                } else {
                    nextAngle = Math.max(getAngle() - 3, temporaryFinalAngel);
                }

                setAngle(nextAngle);
                uiHandler.postDelayed(this, 10);
            }
        });
    }


    private Timer invalidateTimerAndCreateNew(Timer timer, TimerTask timerTask) {
        if (timer != null) {
            timer.cancel();
            timer.purge();
        }


        if (timerTask != null) {
            timerTask.cancel();
        }

        timer = new Timer();
        return timer;
    }
}

for use this class add StickyWheelView instead of WheelView in your xml or java code

@jinchuika
Copy link

I know this is kind of a late time, but were you able to test this with an odd number of items? I found a bug where it doesn't sticks properly with in this case

@prem-p-simform
Copy link

prem-p-simform commented Mar 2, 2021

@shayanpourvatan For which purpose it is used and how to use this component? Can you please share some more info about StickyWheelView.

@shayanpourvatan
Copy link
Author

@jinchuika Sorry for the late answer:
I don't remind this class actually, in one project we need to show one item as sticky, the project started in the hackathon and I write this code, actually, I don't test it in the real application with the dynamic case,

@prem-p-simform For using this class you need to replace it with default wheelView, in XML or Java class, everywhere you have wheelView, simply replace it with this class, but as Jinchuika mentioned, this class might have some issue in the odd number of the items.

I can spend some time fixing it for odd number items, if it's an emergency to you tell me, I will fix issues.

@prem-p-simform
Copy link

@shayanpourvatan I have requirement of sticky item, For example sticky headers. I want to stick item at start of the list.

@shayanpourvatan
Copy link
Author

@prem-p-simform I think you need to search for other libraries, this library as shown on the start page, used for wheel items, I think you need a recyclerView sticky header.

@prem-p-simform
Copy link

prem-p-simform commented Mar 3, 2021

I searched for that, Could not find RecyclerView LayoutManager which satisfy my needs. I need half cirlce layout and it should start from bottom and end in right side. Also item at bottom can be sticky, other can be scrolled.

@shayanpourvatan
Copy link
Author

@prem-p-simform This library is not what you want, I think you must write it by your self or do some hacky way ( I don't have an idea right now )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants