贾艺驰 3 years ago
parent
commit
eb40b3f11d

+ 1 - 0
.gitignore

@@ -13,3 +13,4 @@
 .externalNativeBuild
 .cxx
 .idea/
+output/

+ 2 - 1
app/src/main/AndroidManifest.xml

@@ -19,7 +19,8 @@
         android:supportsRtl="true"
         android:theme="@style/AppTheme"
         android:usesCleartextTraffic="true">
-        <activity android:name=".activity.InputParamActivity"></activity>
+        <activity android:name=".activity.AdminScaleActivity"></activity>
+        <activity android:name=".activity.InputParamActivity" />
         <activity android:name=".activity.WelcomeActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />

+ 3 - 1
app/src/main/java/com/jyc/threegames/App.java

@@ -8,7 +8,9 @@ import com.jyc.threegames.service.GameService;
 public class App extends Application {
     public static Application app;
 
-    public static final String SERVER_ADDRESS = "http://192.168.1.100:8080/";
+//    public static final String SERVER_ADDRESS = "http://192.168.1.100:8080/";
+
+    public static final String SERVER_ADDRESS = "http://8.210.195.183:8080/";
 
     public static boolean CAN_PLAY_GAME = true;
 

+ 8 - 3
app/src/main/java/com/jyc/threegames/activity/AdminActivity.java

@@ -29,17 +29,17 @@ public class AdminActivity extends BaseActivity {
 
     @OnClick(R.id.gameA)
     public void goToGameA(){
-        GameActivity.LAUNCH_GAME_ONE(this, GameInfo.EXERCISE(GameInfo.VERSION_GAME_ONE));
+        InputParamActivity.LAUNCH(this, GameInfo.VERSION_GAME_ONE);
     }
 
     @OnClick(R.id.gameB)
     public void goToGameB(){
-        GameActivity.LAUNCH_GAME_ONE(this, GameInfo.EXERCISE(GameInfo.VERSION_GAME_TWO));
+        InputParamActivity.LAUNCH(this, GameInfo.VERSION_GAME_TWO);
     }
 
     @OnClick(R.id.gameC)
     public void goToGameC(){
-        GameActivity.LAUNCH_GAME_ONE(this, GameInfo.EXERCISE(GameInfo.VERSION_GAME_THREE));
+        InputParamActivity.LAUNCH(this, GameInfo.VERSION_GAME_THREE);
     }
 
     @OnClick(R.id.scale)
@@ -51,4 +51,9 @@ public class AdminActivity extends BaseActivity {
     public void clickLogout(){
         doLogout();
     }
+
+//    @OnClick(R.id.scale_log)
+//    public void clickScaleLog(){
+//        startActivity(new Intent(AdminActivity.this, AdminScaleActivity.class));
+//    }
 }

+ 97 - 0
app/src/main/java/com/jyc/threegames/activity/AdminScaleActivity.java

@@ -0,0 +1,97 @@
+package com.jyc.threegames.activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.jyc.threegames.R;
+import com.jyc.threegames.activity.base.BaseActivity;
+import com.jyc.threegames.bean.ScaleLog;
+import com.jyc.threegames.bean.result.ResGamePlayTime;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class AdminScaleActivity extends BaseActivity {
+
+    @BindView(R.id.search_text_nick_name)
+    EditText mETSearchNickName;
+    @BindView(R.id.search_text_sign)
+    EditText mETSearchSign;
+    @BindView(R.id.search_text_schedule)
+    EditText mETSearchSchedule;
+    @BindView(R.id.search_date)
+    TextView mTVSearchDate;
+
+    @BindView(R.id.swipe)
+    SwipeRefreshLayout mSRF;
+    @BindView(R.id.list)
+    ListView mList;
+
+    private String mSearchDate;
+    private List<ScaleLog> mData;
+
+    @Override
+    protected int getRootLayout() {
+        return R.layout.activity_admin_scale;
+    }
+
+    @Override
+    protected void init(Bundle instance) {
+        super.init(instance);
+
+    }
+
+    public class Adapter extends BaseAdapter {
+
+        @Override
+        public int getCount() {
+            return mData.size();
+        }
+
+        @Override
+        public ScaleLog getItem(int i) {
+            return mData.get(i);
+        }
+
+        @Override
+        public long getItemId(int i) {
+            return i;
+        }
+
+        @Override
+        public View getView(int i, View view, ViewGroup viewGroup) {
+            Adapter.ViewHolder holder;
+            if (view == null){
+                view = getLayoutInflater().inflate(R.layout.item_scale, null);
+                holder = new Adapter.ViewHolder(view);
+                view.setTag(holder);
+            } else
+                holder = (Adapter.ViewHolder) view.getTag();
+
+
+            holder.label.setText(getItem(i).nickname);
+
+            return view;
+        }
+
+        public class ViewHolder{
+            @BindView(R.id.label)
+            TextView label;
+
+            public ViewHolder(View root){
+                ButterKnife.bind(this, root);
+            }
+        }
+    }
+}

+ 90 - 0
app/src/main/java/com/jyc/threegames/activity/InputParamActivity.java

@@ -1,16 +1,106 @@
 package com.jyc.threegames.activity;
 
+import androidx.annotation.NonNull;
 import androidx.appcompat.app.AppCompatActivity;
 
+import android.app.Activity;
+import android.content.Intent;
 import android.os.Bundle;
+import android.text.TextUtils;
+import android.widget.EditText;
+import android.widget.Toast;
 
 import com.jyc.threegames.R;
 import com.jyc.threegames.activity.base.BaseActivity;
+import com.jyc.threegames.bean.GameInfo;
+import com.jyc.threegames.bean.result.ResGameInfo;
+
+import butterknife.BindView;
+import butterknife.OnClick;
 
 public class InputParamActivity extends BaseActivity {
 
+    public static final String PARAM_GAME_VERSION = "version";
+
+    @BindView(R.id.display_duration)
+    EditText mETDisplayDuration;
+    @BindView(R.id.interval_duration)
+    EditText mETIntervalDuration;
+    @BindView(R.id.right_number)
+    EditText mETRightNumber;
+    @BindView(R.id.random_number)
+    EditText mETRandomNumber;
+    @BindView(R.id.practise_duration)
+    EditText mETPractiseDuration;
+    @BindView(R.id.practise_number)
+    EditText mETPractiseNumber;
+
+    private int mGameVersion;
+
+    @Override
+    protected void init(Bundle instance) {
+        super.init(instance);
+
+        if (instance == null)
+            mGameVersion = getIntent().getIntExtra(PARAM_GAME_VERSION, GameInfo.VERSION_GAME_ONE);
+        else
+            mGameVersion = instance.getInt(PARAM_GAME_VERSION, GameInfo.VERSION_GAME_ONE);
+    }
+
+    @Override
+    protected void onSaveInstanceState(@NonNull Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt(PARAM_GAME_VERSION, mGameVersion);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        mGameVersion = savedInstanceState.getInt(PARAM_GAME_VERSION, GameInfo.VERSION_GAME_ONE);
+    }
+
+    @OnClick(R.id.go_game)
+    public void clickGoGame(){
+        if (checkValue(mETDisplayDuration.getText().toString().trim(), "請輸入數字顯示時長,並且請輸入大於0的數字") &&
+            checkValue(mETIntervalDuration.getText().toString().trim(), "請輸入數字交換間隔,並且請輸入大於0的數字") &&
+            checkValue(mETRightNumber.getText().toString().trim(), "請輸入正確數字出現次數,並且請輸入大於0的數字") &&
+            checkValue(mETRandomNumber.getText().toString().trim(), "請輸入隨機數字出現次數,並且請輸入大於0的數字") &&
+            checkValue(mETPractiseDuration.getText().toString().trim(), "請輸入用戶熱身時長,並且請輸入大於0的數字") &&
+            checkValue(mETPractiseNumber.getText().toString().trim(), "請輸入練習數字出現的次數,並且請輸入大於0的數字")){
+            RingActivity.LAUNCH(this, new ResGameInfo(mGameVersion,
+                Integer.parseInt(mETIntervalDuration.getText().toString().trim()),
+                Integer.parseInt(mETDisplayDuration.getText().toString().trim()),
+                Integer.parseInt(mETRightNumber.getText().toString().trim()),
+                Integer.parseInt(mETRandomNumber.getText().toString().trim()),
+                Integer.parseInt(mETPractiseDuration.getText().toString().trim()),
+                Integer.parseInt(mETPractiseNumber.getText().toString().trim())));
+            finish();
+        }
+    }
+
     @Override
     protected int getRootLayout() {
         return R.layout.activity_input_param;
     }
+
+    @Override
+    protected String getPageTitle() {
+        return "輸入練習參數";
+    }
+
+    private boolean checkValue(String value, String message){
+        int intValue = Integer.parseInt(value);
+        if (TextUtils.isEmpty(value) || intValue <= 0){
+            Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+            return false;
+        }
+
+        return true;
+    }
+
+    public static void LAUNCH(Activity context, int gameVersion){
+        Intent intent = new Intent(context, InputParamActivity.class);
+        intent.putExtra(PARAM_GAME_VERSION, gameVersion);
+        context.startActivity(intent);
+    }
 }

+ 8 - 0
app/src/main/java/com/jyc/threegames/bean/PageInfo.java

@@ -0,0 +1,8 @@
+package com.jyc.threegames.bean;
+
+import java.util.List;
+
+public class PageInfo<T> {
+    public long total;
+    public List<T> list;
+}

+ 21 - 0
app/src/main/java/com/jyc/threegames/bean/ScaleLog.java

@@ -0,0 +1,21 @@
+package com.jyc.threegames.bean;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+public class ScaleLog {
+    public Long id;
+    public String nickname;
+    public Long userId;
+    public String getUp;
+    public String contact;
+    public String work;
+    public String dinner;
+    public String sleep;
+    public Date createDate;
+    public Date eventDate;
+    public String sign;
+    public BigDecimal schedule;
+    public Date startDate;
+    public String deviceId;
+}

+ 8 - 0
app/src/main/java/com/jyc/threegames/bean/SearchInfo.java

@@ -0,0 +1,8 @@
+package com.jyc.threegames.bean;
+
+public class SearchInfo {
+    public String nickname;
+    public String eventDate;
+    public String sign;
+    public String schedule;
+}

+ 11 - 0
app/src/main/java/com/jyc/threegames/bean/result/ResGameInfo.java

@@ -15,6 +15,17 @@ public class ResGameInfo implements Parcelable {
     public int playGameType = -1; //量表还是游戏 0:游戏 1:量表
     public boolean needDoGame = false;
 
+    public ResGameInfo(int gameVersion, long intervalDuration, long displayDuration, int correctNumberOccurrenceNumber, int errorNumberOccurrenceNumber, long practiseDuration, int practiseOccurrenceNumber) {
+        this.playGameType = GAME_TYPE_GAME;
+        this.gameVersion = gameVersion;
+        this.intervalDuration = intervalDuration;
+        this.displayDuration = displayDuration;
+        this.correctNumberOccurrenceNumber = correctNumberOccurrenceNumber;
+        this.errorNumberOccurrenceNumber = errorNumberOccurrenceNumber;
+        this.practiseDuration = practiseDuration;
+        this.practiseOccurrenceNumber = practiseOccurrenceNumber;
+    }
+
     public int gameVersion; //游戏版本
     public long intervalDuration; //數字交換間隔
     public long displayDuration;//顯示時長

+ 15 - 0
app/src/main/java/com/jyc/threegames/controller/GameController.java

@@ -5,6 +5,9 @@ import com.jyc.threegames.App;
 import com.jyc.threegames.bean.ControllerMessage;
 import com.jyc.threegames.bean.GameAnswer;
 import com.jyc.threegames.bean.GameInfo;
+import com.jyc.threegames.bean.PageInfo;
+import com.jyc.threegames.bean.ScaleLog;
+import com.jyc.threegames.bean.SearchInfo;
 import com.jyc.threegames.bean.result.ResGameInfo;
 import com.jyc.threegames.bean.result.ResGamePlayTime;
 import com.jyc.threegames.net.ResData;
@@ -19,6 +22,7 @@ import java.util.List;
 import java.util.Locale;
 
 import io.reactivex.Observable;
+import io.reactivex.functions.Function;
 import retrofit2.http.Field;
 
 public class GameController extends BaseController {
@@ -49,6 +53,17 @@ public class GameController extends BaseController {
         return mService;
     }
 
+    public Observable<ControllerMessage<List<ScaleLog>>> list(SearchInfo search, int pageIndex, int pageSize){
+        return getGameService().list(new Gson().toJson(search), pageIndex, pageSize)
+            .map(new Function<ResData<PageInfo<ScaleLog>>, ControllerMessage<List<ScaleLog>>>() {
+                @Override
+                public ControllerMessage<List<ScaleLog>> apply(ResData<PageInfo<ScaleLog>> data) throws Exception {
+                    return ControllerMessage.getSimpleMessage(data.isRequestSuccess(), data.message, data.data != null ? data.data.list : null);
+                }
+            });
+
+    }
+
     public Observable<ControllerMessage<ResGameInfo>> needPlayGame(){
         return getGameService().questNeedPlayGame()
             .map(new SimpleDataHandleFunction<>());

+ 7 - 0
app/src/main/java/com/jyc/threegames/net/api/GameService.java

@@ -1,5 +1,7 @@
 package com.jyc.threegames.net.api;
 
+import com.jyc.threegames.bean.PageInfo;
+import com.jyc.threegames.bean.ScaleLog;
 import com.jyc.threegames.bean.result.ResGameInfo;
 import com.jyc.threegames.bean.result.ResGamePlayTime;
 import com.jyc.threegames.net.ResData;
@@ -13,6 +15,11 @@ import retrofit2.http.GET;
 import retrofit2.http.POST;
 
 public interface GameService {
+
+    @FormUrlEncoded
+    @POST("scale/log/list")
+    Observable<ResData<PageInfo<ScaleLog>>> list(@Field("search") String search, @Field("page") int page, @Field("size") int size);
+
     @GET("push/log/needPlayGame")
     Observable<ResData<ResGameInfo>> questNeedPlayGame();
 

+ 3 - 0
app/src/main/java/com/jyc/threegames/service/GameService.java

@@ -6,6 +6,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.IBinder;
+import android.widget.Toast;
 
 import androidx.annotation.Nullable;
 
@@ -21,10 +22,12 @@ public class GameService extends Service {
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            Toast.makeText(context, "接收到通知", Toast.LENGTH_LONG).show();
             if (App.CAN_PLAY_GAME && LoginController.getInstance().getCurrentLoginInfo() != null && !LoginController.getInstance().isCurrentUserAdmin())
                 new SimpleRequest<ResGameInfo>().request(context, GameController.getInstance().needPlayGame(), new SimpleRequest.Executor<ResGameInfo>() {
                     @Override
                     public void execute(ResGameInfo obj) {
+                        Toast.makeText(context, "已發送推送", Toast.LENGTH_LONG).show();
                         if (App.CAN_PLAY_GAME && obj != null && obj.needDoGame){
                             RingActivity.LAUNCH(App.app, obj);
                         }

+ 1 - 0
app/src/main/res/layout/activity_admin.xml

@@ -177,6 +177,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:background="#9A64B2"
+                android:id="@+id/scale_log"
                 android:layout_marginTop="10dp">
                 <TextView
                     android:id="@+id/view_scale_record_title"

+ 104 - 0
app/src/main/res/layout/activity_admin_scale.xml

@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout 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"
+    tools:context=".activity.AdminScaleActivity">
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="0dp"
+        android:fitsSystemWindows="true"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        android:background="@color/colorAccent"
+        android:minHeight="?attr/actionBarSize" >
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:textSize="20sp"
+            android:textStyle="bold"/>
+
+        <TextView
+            android:id="@+id/search"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:textSize="14sp"
+            android:text="搜索"
+            android:layout_marginEnd="10dp"
+            android:textStyle="bold"/>
+    </androidx.appcompat.widget.Toolbar>
+
+    <EditText
+        android:id="@+id/search_text_nick_name"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toBottomOf="@id/toolbar"
+        app:layout_constraintStart_toStartOf="parent"
+        android:singleLine="true"
+        android:hint="輸入用戶名搜索"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+
+    <EditText
+        android:id="@+id/search_text_sign"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toBottomOf="@id/search_text_nick_name"
+        app:layout_constraintStart_toStartOf="parent"
+        android:singleLine="true"
+        android:hint="輸入序號搜索"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <EditText
+        android:id="@+id/search_text_schedule"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toBottomOf="@id/search_text_sign"
+        app:layout_constraintStart_toStartOf="parent"
+        android:singleLine="true"
+        android:hint="輸入完成度搜索"
+        app:layout_constraintEnd_toEndOf="parent"/>
+
+    <TextView
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        app:layout_constraintEnd_toStartOf="@id/clear_date"
+        android:id="@+id/search_date"
+        android:text="點擊選擇日期搜索"
+        android:layout_marginTop="5dp"
+        android:layout_marginStart="5dp"
+        app:layout_constraintStart_toStartOf="parent"
+        android:textSize="18sp"
+        app:layout_constraintTop_toBottomOf="@id/search_text_schedule"/>
+
+    <Button
+        android:id="@+id/clear_date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="清空日期"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/search_date"
+        app:layout_constraintBottom_toBottomOf="@id/search_date"/>
+
+
+    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:id="@+id/swipe"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/search_date"
+        app:layout_constraintBottom_toBottomOf="parent">
+        <ListView
+            android:id="@+id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 141 - 1
app/src/main/res/layout/activity_input_param.xml

@@ -33,5 +33,145 @@
             android:layout_marginEnd="10dp"
             android:textStyle="bold"/>
     </androidx.appcompat.widget.Toolbar>
-    
+
+    <TextView
+        android:id="@+id/view_label_display_duration"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="數字顯示時常"
+        android:layout_marginStart="10dp"
+        android:layout_marginTop="10dp"
+        app:layout_constraintTop_toBottomOf="@id/toolbar"
+        app:layout_constraintStart_toStartOf="parent"/>
+
+    <EditText
+        android:id="@+id/display_duration"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="2000"
+        android:hint="ms"
+        app:layout_constraintTop_toTopOf="@id/view_label_display_duration"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_display_duration"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/view_label_interval_duration"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="數字交換間隔"
+        android:layout_marginTop="30dp"
+        app:layout_constraintTop_toBottomOf="@id/view_label_display_duration"
+        app:layout_constraintStart_toStartOf="@id/view_label_display_duration"/>
+
+    <EditText
+        android:id="@+id/interval_duration"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="2000"
+        android:hint="ms"
+        app:layout_constraintTop_toTopOf="@id/view_label_interval_duration"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_interval_duration"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
+
+    <TextView
+        android:id="@+id/view_label_right_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="正確數字出現次數"
+        android:layout_marginTop="30dp"
+        app:layout_constraintTop_toBottomOf="@id/view_label_interval_duration"
+        app:layout_constraintStart_toStartOf="@id/view_label_display_duration"/>
+
+    <EditText
+        android:id="@+id/right_number"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="2"
+        android:hint="個"
+        app:layout_constraintTop_toTopOf="@id/view_label_right_number"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_right_number"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/view_label_random_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="隨機數字出現次數"
+        android:layout_marginTop="30dp"
+        app:layout_constraintTop_toBottomOf="@id/view_label_right_number"
+        app:layout_constraintStart_toStartOf="@id/view_label_display_duration"/>
+
+    <EditText
+        android:id="@+id/random_number"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="5"
+        android:hint="個"
+        app:layout_constraintTop_toTopOf="@id/view_label_random_number"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_random_number"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/view_label_practise_duration"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="用戶熱身時長"
+        android:layout_marginTop="30dp"
+        app:layout_constraintTop_toBottomOf="@id/view_label_random_number"
+        app:layout_constraintStart_toStartOf="@id/view_label_display_duration"/>
+
+    <EditText
+        android:id="@+id/practise_duration"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="5000"
+        android:hint="ms"
+        app:layout_constraintTop_toTopOf="@id/view_label_practise_duration"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_practise_duration"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/view_label_practise_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="練習數字出現的次數"
+        android:layout_marginTop="30dp"
+        app:layout_constraintTop_toBottomOf="@id/view_label_practise_duration"
+        app:layout_constraintStart_toStartOf="@id/view_label_display_duration"/>
+
+    <EditText
+        android:id="@+id/practise_number"
+        android:layout_width="100dp"
+        android:singleLine="true"
+        android:inputType="number"
+        android:digits="0123456789"
+        android:text="5"
+        android:hint="個"
+        app:layout_constraintTop_toTopOf="@id/view_label_practise_number"
+        app:layout_constraintBottom_toBottomOf="@id/view_label_practise_number"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:layout_marginEnd="10dp"
+        android:layout_height="wrap_content"/>
+
 </androidx.constraintlayout.widget.ConstraintLayout>

BIN
output/release/app-release.apk


BIN
output/release/release.zip