The beginning of the story

Recently there was a demand for a lottery wheel for successful payments. I had a look at GayHub and saw how I could do it.

Written on the topic before

This thing is on Github and a project is an extension. But there was a gap between the implementation time and the download time. So I can’t find the original chain can’t hang, please forgive me. If you know the original link, please leave it in the comments and I’ll add it later.

rendering

As usual first to the final implementation effect GIF (GIF should be the time to extract the frame. The actual effect is better than the picture)

Implementation approach

1. Draw the prize View 2, which can switch the background, and arrange it into nine grids 3. Create a feeling of rotation by transforming the two views before and after

code

  1. PrizeItemView
<? xml version="1.0" encoding="utf-8"? > <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_white">

    <View
        android:id="@+id/overlay"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/shape_pink"
        android:visibility="invisible" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/iv_prize"
            android:layout_width="60dp"
            android:layout_height="45dp"
            android:src="@drawable/png_prize" />

        <TextView
            android:id="@+id/tv_prize_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="9dp"
            android:text="A prize."
            android:textColor="#98520E"
            android:textSize="22sp" />
    </LinearLayout>
</FrameLayout>
Copy the code

/** * Created by Huahen on 2021/10/25 * ClassDescription: Lucky draw - Awards sub-view */
public class PrizeItemView extends FrameLayout implements PrizeItemApi {

    private Context mContext;
    private View mOverlay;
    private ImageView ivPrize;
    private TextView tvPrize;

    public PrizeItemView(@NonNull Context context) {
        this(context, null);
    }


    public PrizeItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PrizeItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        inflate(context, R.layout.item_prize, this);
        mOverlay = findViewById(R.id.overlay);
        ivPrize = findViewById(R.id.iv_prize);
        tvPrize = findViewById(R.id.tv_prize_name);
        mContext = context;
    }


    @Override
    public void setFocus(boolean isFocused) {
        if(mOverlay ! =null) { mOverlay.setVisibility(isFocused ? INVISIBLE : VISIBLE); }}@Override
    public void setUi(PrizeListBean bean) { ivPrize.setImageResource(bean.getPrize_path()); tvPrize.setText(bean.getGoodName()); }}Copy the code
/** * Created by huahen on 2021/10/25 * ClassDescription : */
public interface PrizeItemApi {

    void setFocus(boolean isFocused);// Change the current display status

    void setUi(PrizeListBean bean);
}

Copy the code
I've written a custom View that implements two methods. 1, update the prize data modify UI 2, update the prize selection backgroundCopy the code
  1. First of all, the layout is made up of 8 PrizeItemViews, hahaha, with an IV in the middle and a LuckDrawView found online
<? xml version="1.0" encoding="utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="4dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item8"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />

        <ImageView
            android:id="@+id/iv_start"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1"
            android:background="@drawable/luck_draw_btn" />

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_weight="1"
        android:orientation="horizontal">

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item7"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item6"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />

        <com.huahen.luckdraw.luckDrawView.PrizeItemView
            android:id="@+id/item5"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginRight="8dp"
            android:layout_weight="1" />
    </LinearLayout>

</LinearLayout>
Copy the code
It looks like thisCopy the code

Is here. Full text of the most important codeCopy the code
public class LuckDrawView extends FrameLayout {
    private PrizeItemView itemView1, itemView2, itemView3,
            itemView8, itemView4,
            itemView7, itemView6, itemView5;
    private ImageView ivStart;
    private OnItemListener listener;

    private PrizeItemApi[] itemViewArr = new PrizeItemApi[8];

    private int currentIndex = 0;
    private int currentTotal = 0;
    private int stayIndex = 0;

    private boolean isMarqueeRunning = false;//
    private boolean isGameRunning = false; // Whether it is in rotation
    private boolean isTryToStop = false;// Whether to speed up/slow down

    private static final int DEFAULT_SPEED = 150; // Default/slowest speed
    private static final int MIN_SPEED = 50;// The fastest speed
    private int currentSpeed = DEFAULT_SPEED;// Current speed

    Timer timer = new Timer();


    public LuckDrawView(@NonNull Context context) {
        this(context, null);
    }

    public LuckDrawView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LuckDrawView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        inflate(context, R.layout.view_luck_draw_nine, this);
        initView();
    }

    @Override
    protected void onAttachedToWindow(a) {
        super.onAttachedToWindow();
        startMarquee();
    }

    @Override
    protected void onDetachedFromWindow(a) {
        stopMarquee();
        super.onDetachedFromWindow();
    }


    private void initView(a) {
        itemView1 = (PrizeItemView) findViewById(R.id.item1);
        itemView2 = (PrizeItemView) findViewById(R.id.item2);
        itemView3 = (PrizeItemView) findViewById(R.id.item3);
        itemView4 = (PrizeItemView) findViewById(R.id.item4);
        itemView5 = (PrizeItemView) findViewById(R.id.item5);
        itemView6 = (PrizeItemView) findViewById(R.id.item6);
        itemView7 = (PrizeItemView) findViewById(R.id.item7);
        itemView8 = (PrizeItemView) findViewById(R.id.item8);

        itemViewArr[0] = itemView1;
        itemViewArr[1] = itemView2;
        itemViewArr[2] = itemView3;
        itemViewArr[3] = itemView4;
        itemViewArr[4] = itemView5;
        itemViewArr[5] = itemView6;
        itemViewArr[6] = itemView7;
        itemViewArr[7] = itemView8;


        ivStart = findViewById(R.id.iv_start);
        ivStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) { listener.onClick(); }}); }private void stopMarquee(a) {
        isMarqueeRunning = false;
        isGameRunning = false;
        isTryToStop = false;
    }


    private void startMarquee(a) {
        isMarqueeRunning = true;
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                while (isMarqueeRunning) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
/ / / / light band
// post(new Runnable() {
// @Override
// public void run() {
// if (bg_1 ! = null && bg_2 ! = null) {
// if (VISIBLE == bg_1.getVisibility()) {
// bg_1.setVisibility(GONE);
// bg_2.setVisibility(VISIBLE);
// } else {
// bg_1.setVisibility(VISIBLE);
// bg_2.setVisibility(GONE);
/ /}
/ /}
/ /}
/ /});
                }
            }
        }).start();
    }

    // Get the sleep time, i.e. the rotation speed, the smaller the faster.
    private long getInterruptTime(a) {
        currentTotal++;
        if (isTryToStop) {// Slow down until you return to the default speed
            currentSpeed += 10;
            if(currentSpeed > DEFAULT_SPEED) { currentSpeed = DEFAULT_SPEED; }}else {// Increase to the maximum speed
            // Do no acceleration in the first lap
            if (currentTotal / itemViewArr.length > 0) {
                currentSpeed -= 10;
            }
            if(currentSpeed < MIN_SPEED) { currentSpeed = MIN_SPEED; }}return currentSpeed;
    }

    // Return the current status
    public boolean isGameRunning(a) {
        return isGameRunning;
    }

    // Start the lottery
    public void startGame(final int stayIndex) {
        if (isGameRunning) {/ / sports
            return;
        }
        isGameRunning = true;
        isTryToStop = false;
        currentSpeed = DEFAULT_SPEED;
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                while (isGameRunning) {
                    try {
                        Thread.sleep(getInterruptTime());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    post(new Runnable() {
                        @Override
                        public void run(a) {
                            // Prevent the thread from going one more time
                            if(! isGameRunning) {return;
                            }
                            int preIndex = currentIndex;
                            currentIndex++;
                            if (currentIndex >= itemViewArr.length) {
                                currentIndex = 0;
                            }

                            // Implement rotation effect according to the view transformation of the two ItemViews
                            itemViewArr[preIndex].setFocus(true);
                            itemViewArr[currentIndex].setFocus(false);

                            // Slow down && speed to the minimum && Current view is the specified view -- stop
                            if (isTryToStop && currentSpeed == DEFAULT_SPEED && stayIndex == currentIndex) {
                                isGameRunning = false; listener.onShop(currentIndex); }}}); } } }).start();// Decelerate in 5 seconds
        timer.schedule(new TimerTask() {
            @Override
            public void run(a) { tryToStop(); }},5000);
    }


    // Change the acceleration state
    public void tryToStop(a) {
        isTryToStop = true;
    }


    public void setData(List<PrizeListBean> beans) {
        if(beans ! =null) {
            for (int i = 0; i < beans.size(); i++) { itemViewArr[i].setUi(beans.get(i)); }}}public void setOnItemListener(OnItemListener listener) {
        this.listener = listener;
    }

    // Set an interface to listen for events
    public interface OnItemListener {
        void onClick(a);// Click Start

        void onShop(int Index);// The rotation stops}}Copy the code

Such a clear note, I should not explain how

Finally, call

        mLuckDrawView = findViewById(R.id.luck_draw);
        mLuckDrawView.setOnItemListener(new LuckDrawView.OnItemListener() {
            @Override
            public void onClick(a) {// Start the lottery
                int stayIndex = new Random().nextInt(8);
                mLuckDrawView.startGame(stayIndex);
            }

            @Override
            public void onShop(int Index) {// Animation stops
                Toast.makeText(MainActivity.this."This is number one." + Index + "A commodity", Toast.LENGTH_SHORT).show(); }}); mLuckDrawView.setData(getLuckDrawData());// Set the prize data
Copy the code

And just like that, a lottery wheel was realized

It may not be perfect, but it’s an idea I’m offering. You are also welcome to join the discussion.

It is not easy for the author to write here, if this article helps you. Please feel free to give me a thumbs up if you have a different opinion. Feel free to join us in the comments section