Sfoglia il codice sorgente

1.添加训练内容详情接口

王鹏鹏 2 anni fa
parent
commit
52ae108b43

+ 3 - 1
.idea/misc.xml

@@ -45,6 +45,7 @@
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/bg_training_content_title.xml" value="0.2165" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/bg_work_benches_btn.xml" value="0.2265" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/layer_tab_indicator.xml" value="0.2265" />
+        <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/selector.xml" value="0.219" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/selector_train_radio.xml" value="0.2265" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/selector_train_radio_checked.xml" value="0.2265" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/drawable/selector_train_radio_unchecked.xml" value="0.2265" />
@@ -61,7 +62,7 @@
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_brain_ability.xml" value="0.21014492753623187" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_free_training.xml" value="0.21014492753623187" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_task.xml" value="0.6" />
-        <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_train_content.xml" value="0.22108843537414966" />
+        <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_train_content.xml" value="0.33808844507845937" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/fragment_train_report.xml" value="0.22826086956521738" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/item_course_treatment.xml" value="0.1" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/item_free_training.xml" value="0.8800000000000001" />
@@ -71,6 +72,7 @@
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/item_train_report.xml" value="0.536" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/item_training_content.xml" value="0.264" />
         <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/item_training_content_details.xml" value="0.1" />
+        <entry key="..\:/workspace/hcp-pad/workbenches/src/main/res/layout/spinner_list_item.xml" value="0.1" />
         <entry key="..\:/workspace/yingyangfly/app/src/main/res/layout/activity_main.xml" value="0.22826086956521738" />
         <entry key="..\:/workspace/yingyangfly/app/src/main/res/layout/activity_push.xml" value="0.22239583333333332" />
         <entry key="..\:/workspace/yingyangfly/baselib/src/main/res/drawable/bg_center_toast.xml" value="0.2265" />

+ 1 - 1
baselib/src/main/java/com/yingyangfly/baselib/voice/PlayVoice.kt

@@ -113,7 +113,7 @@ class PlayVoice {
     }
 
     private fun print(message: String) {
-        Log.i("wpp", message)
+        Log.i("baidu", message)
     }
 
     private fun checkResult(result: Int, method: String) {

+ 1 - 2
config.gradle

@@ -115,8 +115,7 @@ ext {
             "leakcanary"             : 'com.squareup.leakcanary:leakcanary-android:2.10',
             "LiteAVSDK_Player"       : 'com.tencent.liteav:LiteAVSDK_Player:latest.release',
             "imsdk"                  : 'com.tencent.imsdk:imsdk:5.1.66',
-            "rxbus"                  : 'lib.gorden.rxbus2:rxbus:2.0.1',
-            "nice_spinner"           : 'com.github.arcadefire:nice-spinner:1.4.4'
+            "rxbus"                  : 'lib.gorden.rxbus2:rxbus:2.0.1'
 
     ]
 }

+ 0 - 1
workbenches/build.gradle

@@ -21,6 +21,5 @@ dependencies {
     implementation(rootProject.ext.androidx.appcompat)
     implementation(rootProject.ext.androidx.material)
     implementation(rootProject.ext.androidx.constraintlayout)
-    implementation(rootProject.ext.dependencies.nice_spinner)
 
 }

+ 2 - 2
workbenches/src/main/java/com/yingyang/workbenches/WorkbenchesActivity.kt

@@ -42,7 +42,7 @@ class WorkbenchesActivity : BaseMVVMActivity<ActivityWorkbenchesBinding, Workben
     override fun initViews() {
         playVoice = PlayVoice()
         playVoice?.setContext(this)
-//        playVoice?.speak("你好啊")
+        playVoice?.speak("你好啊")
         binding {
             //推荐游戏列表
             rvGame.layoutManager = GridLayoutManager(this@WorkbenchesActivity, 4)
@@ -126,7 +126,7 @@ class WorkbenchesActivity : BaseMVVMActivity<ActivityWorkbenchesBinding, Workben
 
     override fun initData() {
 //        showTipDialog()
-        showTaskDialog()
+//        showTaskDialog()
     }
 
     /**

+ 18 - 7
workbenches/src/main/java/com/yingyang/workbenches/traincontent/TrainContentFragment.kt

@@ -1,9 +1,11 @@
 package com.yingyang.workbenches.traincontent
 
+import android.text.SpannableString
 import com.yingyang.workbenches.adapter.TrainContentAdapter
 import com.yingyang.workbenches.databinding.FragmentTrainContentBinding
 import com.yingyang.workbenches.entity.TreatmentBean
-import com.yingyangfly.baselib.ext.setOnSingleClickListener
+import com.yingyang.workbenches.widget.OnSpinnerItemSelectedListener
+import com.yingyang.workbenches.widget.SpinnerTextFormatter
 import com.yingyangfly.baselib.ext.toast
 import com.yingyangfly.baselib.mvvm.BaseMVVMFragment
 import com.yingyangfly.baselib.router.RouterUrlCommon
@@ -18,7 +20,9 @@ import gorden.rxbus2.ThreadMode
 class TrainContentFragment :
     BaseMVVMFragment<FragmentTrainContentBinding, TrainContentViewModel>() {
 
-    private var treatmentList = mutableListOf<TreatmentBean>()
+    /**
+     * 训练内容adapter
+     */
     private val adapter by lazy { TrainContentAdapter() }
 
     override fun initViews() {
@@ -31,9 +35,11 @@ class TrainContentFragment :
     }
 
     override fun initListener() {
-        binding.courselayout.setOnSingleClickListener {
-
-        }
+        binding.treatmentSpinner.onSpinnerItemSelectedListener =
+            OnSpinnerItemSelectedListener { parent, view, position, id ->
+                val bean = binding.treatmentSpinner.selectedItem as TreatmentBean
+                findMyTask(bean.id)
+            }
     }
 
     override fun initData() {
@@ -49,12 +55,17 @@ class TrainContentFragment :
     }
 
     private fun findAllTreatment() {
-        treatmentList.clear()
         viewModel.findAllTreatment(fail = {
             it.toast()
         }, success = {
             if (it.isNullOrEmpty().not()) {
-                treatmentList.addAll(it)
+                val textFormatter: SpinnerTextFormatter<*> =
+                    SpinnerTextFormatter { bean: TreatmentBean ->
+                        SpannableString(bean.name)
+                    }
+                binding.treatmentSpinner.setSpinnerTextFormatter(textFormatter)
+                binding.treatmentSpinner.setSelectedTextFormatter(textFormatter)
+                binding.treatmentSpinner.attachDataSource(it)
             }
         })
     }

+ 460 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/NiceSpinner.java

@@ -0,0 +1,460 @@
+package com.yingyang.workbenches.widget;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.ListPopupWindow;
+import android.widget.ListView;
+import android.widget.PopupWindow;
+
+import androidx.annotation.ColorRes;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
+
+import com.yingyang.workbenches.R;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NiceSpinner extends AppCompatTextView {
+
+    private static final int MAX_LEVEL = 10000;
+    private static final int VERTICAL_OFFSET = 1;
+    private static final String INSTANCE_STATE = "instance_state";
+    private static final String SELECTED_INDEX = "selected_index";
+    private static final String IS_POPUP_SHOWING = "is_popup_showing";
+    private static final String IS_ARROW_HIDDEN = "is_arrow_hidden";
+    private static final String ARROW_DRAWABLE_RES_ID = "arrow_drawable_res_id";
+
+    private int selectedIndex;
+    private Drawable arrowDrawable;
+    private ListPopupWindow popupWindow;
+    private NiceSpinnerBaseAdapter adapter;
+
+    private AdapterView.OnItemClickListener onItemClickListener;
+    private AdapterView.OnItemSelectedListener onItemSelectedListener;
+    private OnSpinnerItemSelectedListener onSpinnerItemSelectedListener;
+
+    private boolean isArrowHidden;
+    private int backgroundSelector;
+    private int arrowDrawableTint;
+    private int displayHeight;
+    private int parentVerticalOffset;
+    private @DrawableRes
+    int arrowDrawableResId;
+    private SpinnerTextFormatter spinnerTextFormatter = new SimpleSpinnerTextFormatter();
+    private SpinnerTextFormatter selectedTextFormatter = new SimpleSpinnerTextFormatter();
+    private PopUpTextAlignment horizontalAlignment;
+
+    @Nullable
+    private ObjectAnimator arrowAnimator = null;
+
+    public NiceSpinner(Context context) {
+        super(context);
+        init(context, null);
+    }
+
+    public NiceSpinner(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs);
+    }
+
+    public NiceSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs);
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
+        bundle.putInt(SELECTED_INDEX, selectedIndex);
+        bundle.putBoolean(IS_ARROW_HIDDEN, isArrowHidden);
+        bundle.putInt(ARROW_DRAWABLE_RES_ID, arrowDrawableResId);
+        if (popupWindow != null) {
+            bundle.putBoolean(IS_POPUP_SHOWING, popupWindow.isShowing());
+        }
+        return bundle;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable savedState) {
+        if (savedState instanceof Bundle) {
+            Bundle bundle = (Bundle) savedState;
+            selectedIndex = bundle.getInt(SELECTED_INDEX);
+            if (adapter != null) {
+                setTextInternal(selectedTextFormatter.format(adapter.getItemInDataset(selectedIndex)).toString());
+                adapter.setSelectedIndex(selectedIndex);
+            }
+
+            if (bundle.getBoolean(IS_POPUP_SHOWING)) {
+                if (popupWindow != null) {
+                    // Post the show request into the looper to avoid bad token exception
+                    post(this::showDropDown);
+                }
+            }
+            isArrowHidden = bundle.getBoolean(IS_ARROW_HIDDEN, false);
+            arrowDrawableResId = bundle.getInt(ARROW_DRAWABLE_RES_ID);
+            savedState = bundle.getParcelable(INSTANCE_STATE);
+        }
+        super.onRestoreInstanceState(savedState);
+    }
+
+    private void init(Context context, AttributeSet attrs) {
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NiceSpinner);
+        setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
+        setClickable(true);
+        backgroundSelector = typedArray.getResourceId(R.styleable.NiceSpinner_backgroundSelector, R.drawable.selector);
+        setBackgroundResource(backgroundSelector);
+        popupWindow = new ListPopupWindow(context);
+        popupWindow.setOnItemClickListener((parent, view, position, id) -> {
+            // The selected item is not displayed within the list, so when the selected position is equal to
+            // the one of the currently selected item it gets shifted to the next item.
+            if (position >= selectedIndex && position < adapter.getCount()) {
+                position++;
+            }
+            selectedIndex = position;
+
+            if (onSpinnerItemSelectedListener != null) {
+                onSpinnerItemSelectedListener.onItemSelected(NiceSpinner.this, view, position, id);
+            }
+
+            if (onItemClickListener != null) {
+                onItemClickListener.onItemClick(parent, view, position, id);
+            }
+
+            if (onItemSelectedListener != null) {
+                onItemSelectedListener.onItemSelected(parent, view, position, id);
+            }
+
+            adapter.setSelectedIndex(position);
+
+            setTextInternal(adapter.getItemInDataset(position));
+
+            dismissDropDown();
+        });
+
+        popupWindow.setModal(true);
+
+        popupWindow.setOnDismissListener(() -> {
+            if (!isArrowHidden) {
+                animateArrow(false);
+            }
+        });
+
+        isArrowHidden = typedArray.getBoolean(R.styleable.NiceSpinner_hideArrow, false);
+        arrowDrawableTint = typedArray.getColor(R.styleable.NiceSpinner_arrowTint, getResources().getColor(R.color.color_FF4A76FF));
+        arrowDrawableResId = typedArray.getResourceId(R.styleable.NiceSpinner_arrowDrawable, R.mipmap.icon_arrow_down);
+        horizontalAlignment = PopUpTextAlignment.fromId(
+                typedArray.getInt(R.styleable.NiceSpinner_popupTextAlignment, PopUpTextAlignment.CENTER.ordinal())
+        );
+
+        CharSequence[] entries = typedArray.getTextArray(R.styleable.NiceSpinner_entries);
+        if (entries != null) {
+            attachDataSource(Arrays.asList(entries));
+        }
+
+        typedArray.recycle();
+
+        measureDisplayHeight();
+
+    }
+
+    private void measureDisplayHeight() {
+        displayHeight = getContext().getResources().getDisplayMetrics().heightPixels;
+    }
+
+    private int getParentVerticalOffset() {
+        if (parentVerticalOffset > 0) {
+            return parentVerticalOffset;
+        }
+        int[] locationOnScreen = new int[2];
+        getLocationOnScreen(locationOnScreen);
+        return parentVerticalOffset = locationOnScreen[VERTICAL_OFFSET];
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if (arrowAnimator != null) {
+            arrowAnimator.cancel();
+        }
+        super.onDetachedFromWindow();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
+            onVisibilityChanged(this, getVisibility());
+        }
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        arrowDrawable = initArrowDrawable(arrowDrawableTint);
+        setArrowDrawableOrHide(arrowDrawable);
+    }
+
+    private Drawable initArrowDrawable(int drawableTint) {
+        if (arrowDrawableResId == 0) {
+            return null;
+        }
+        Drawable drawable = ContextCompat.getDrawable(getContext(), arrowDrawableResId);
+        if (drawable != null) {
+            // Gets a copy of this drawable as this is going to be mutated by the animator
+            drawable = DrawableCompat.wrap(drawable).mutate();
+            if (drawableTint != Integer.MAX_VALUE && drawableTint != 0) {
+                DrawableCompat.setTint(drawable, drawableTint);
+            }
+        }
+        return drawable;
+    }
+
+    private void setArrowDrawableOrHide(Drawable drawable) {
+        if (!isArrowHidden && drawable != null) {
+            setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null);
+        } else {
+            setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+        }
+    }
+
+    private int getDefaultTextColor(Context context) {
+        TypedValue typedValue = new TypedValue();
+        context.getTheme()
+                .resolveAttribute(android.R.attr.textColorPrimary, typedValue, true);
+        TypedArray typedArray = context.obtainStyledAttributes(typedValue.data,
+                new int[]{android.R.attr.textColorPrimary});
+        int defaultTextColor = typedArray.getColor(0, Color.BLACK);
+        typedArray.recycle();
+        return defaultTextColor;
+    }
+
+    public Object getItemAtPosition(int position) {
+        return adapter.getItemInDataset(position);
+    }
+
+    public Object getSelectedItem() {
+        return adapter.getItemInDataset(selectedIndex);
+    }
+
+    public int getSelectedIndex() {
+        return selectedIndex;
+    }
+
+    public void setArrowDrawable(@DrawableRes @ColorRes int drawableId) {
+        arrowDrawableResId = drawableId;
+        arrowDrawable = initArrowDrawable(R.mipmap.icon_arrow_down);
+        setArrowDrawableOrHide(arrowDrawable);
+    }
+
+    public void setArrowDrawable(Drawable drawable) {
+        arrowDrawable = drawable;
+        setArrowDrawableOrHide(arrowDrawable);
+    }
+
+    private void setTextInternal(Object item) {
+        if (selectedTextFormatter != null) {
+            setText(selectedTextFormatter.format(item));
+        } else {
+            setText(item.toString());
+        }
+    }
+
+    /**
+     * Set the default spinner item using its index
+     *
+     * @param position the item's position
+     */
+    public void setSelectedIndex(int position) {
+        if (adapter != null) {
+            if (position >= 0 && position <= adapter.getCount()) {
+                adapter.setSelectedIndex(position);
+                selectedIndex = position;
+                setTextInternal(selectedTextFormatter.format(adapter.getItemInDataset(position)).toString());
+            } else {
+                throw new IllegalArgumentException("Position must be lower than adapter count!");
+            }
+        }
+    }
+
+
+    /**
+     * @deprecated use setOnSpinnerItemSelectedListener instead.
+     */
+    @Deprecated
+    public void addOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
+        this.onItemClickListener = onItemClickListener;
+    }
+
+    /**
+     * @deprecated use setOnSpinnerItemSelectedListener instead.
+     */
+    @Deprecated
+    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener onItemSelectedListener) {
+        this.onItemSelectedListener = onItemSelectedListener;
+    }
+
+    public <T> void attachDataSource(@NonNull List<T> list) {
+        adapter = new NiceSpinnerAdapter<>(getContext(), list, backgroundSelector, spinnerTextFormatter, horizontalAlignment);
+        setAdapterInternal(adapter);
+    }
+
+    public void setAdapter(ListAdapter adapter) {
+        this.adapter = new NiceSpinnerAdapterWrapper(getContext(), adapter, backgroundSelector,
+                spinnerTextFormatter, horizontalAlignment);
+        setAdapterInternal(this.adapter);
+    }
+
+    public PopUpTextAlignment getPopUpTextAlignment() {
+        return horizontalAlignment;
+    }
+
+    private <T> void setAdapterInternal(NiceSpinnerBaseAdapter<T> adapter) {
+        if (adapter.getCount() >= 0) {
+            // If the adapter needs to be set again, ensure to reset the selected index as well
+            selectedIndex = 0;
+            popupWindow.setAdapter(adapter);
+            setTextInternal(adapter.getItemInDataset(selectedIndex));
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (isEnabled() && event.getAction() == MotionEvent.ACTION_UP) {
+            if (!popupWindow.isShowing() && adapter.getCount() > 0) {
+                showDropDown();
+            } else {
+                dismissDropDown();
+            }
+        }
+        return super.onTouchEvent(event);
+    }
+
+    private void animateArrow(boolean shouldRotateUp) {
+        int start = shouldRotateUp ? 0 : MAX_LEVEL;
+        int end = shouldRotateUp ? MAX_LEVEL : 0;
+        arrowAnimator = ObjectAnimator.ofInt(arrowDrawable, "level", start, end);
+        arrowAnimator.setInterpolator(new LinearOutSlowInInterpolator());
+        arrowAnimator.start();
+    }
+
+    public void dismissDropDown() {
+        if (!isArrowHidden) {
+            animateArrow(false);
+        }
+        popupWindow.dismiss();
+    }
+
+    public void showDropDown() {
+        if (!isArrowHidden) {
+            animateArrow(true);
+        }
+        popupWindow.setAnchorView(this);
+        popupWindow.show();
+        final ListView listView = popupWindow.getListView();
+        if (listView != null) {
+            listView.setVerticalScrollBarEnabled(false);
+            listView.setHorizontalScrollBarEnabled(false);
+            listView.setVerticalFadingEdgeEnabled(false);
+            listView.setHorizontalFadingEdgeEnabled(false);
+        }
+    }
+
+
+    private int getPopUpHeight() {
+        return Math.max(verticalSpaceBelow(), verticalSpaceAbove());
+    }
+
+    private int verticalSpaceAbove() {
+        return getParentVerticalOffset();
+    }
+
+    private int verticalSpaceBelow() {
+        return displayHeight - getParentVerticalOffset() - getMeasuredHeight();
+    }
+
+    public void setTintColor(@ColorRes int resId) {
+        if (arrowDrawable != null && !isArrowHidden) {
+            DrawableCompat.setTint(arrowDrawable, ContextCompat.getColor(getContext(), resId));
+        }
+    }
+
+    public void setArrowTintColor(int resolvedColor) {
+        if (arrowDrawable != null && !isArrowHidden) {
+            DrawableCompat.setTint(arrowDrawable, resolvedColor);
+        }
+    }
+
+    public void hideArrow() {
+        isArrowHidden = true;
+        setArrowDrawableOrHide(arrowDrawable);
+    }
+
+    public void showArrow() {
+        isArrowHidden = false;
+        setArrowDrawableOrHide(arrowDrawable);
+    }
+
+    public boolean isArrowHidden() {
+        return isArrowHidden;
+    }
+
+    public void setSpinnerTextFormatter(SpinnerTextFormatter spinnerTextFormatter) {
+        this.spinnerTextFormatter = spinnerTextFormatter;
+    }
+
+    public void setSelectedTextFormatter(SpinnerTextFormatter textFormatter) {
+        this.selectedTextFormatter = textFormatter;
+    }
+
+
+    public void performItemClick(int position, boolean showDropdown) {
+        if (showDropdown) {
+            showDropDown();
+        }
+        setSelectedIndex(position);
+    }
+
+    /**
+     * only applicable when popup is shown .
+     *
+     * @param view
+     * @param position
+     * @param id
+     */
+    public void performItemClick(View view, int position, int id) {
+        showDropDown();
+        final ListView listView = popupWindow.getListView();
+        if (listView != null) {
+            listView.performItemClick(view, position, id);
+        }
+    }
+
+    public OnSpinnerItemSelectedListener getOnSpinnerItemSelectedListener() {
+        return onSpinnerItemSelectedListener;
+    }
+
+    public void setOnSpinnerItemSelectedListener(OnSpinnerItemSelectedListener onSpinnerItemSelectedListener) {
+        this.onSpinnerItemSelectedListener = onSpinnerItemSelectedListener;
+    }
+
+}

+ 55 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/NiceSpinnerAdapter.java

@@ -0,0 +1,55 @@
+package com.yingyang.workbenches.widget;
+
+import android.content.Context;
+
+import java.util.List;
+
+/*
+ * Copyright (C) 2015 Angelo Marchesin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class NiceSpinnerAdapter<T> extends NiceSpinnerBaseAdapter {
+
+    private final List<T> items;
+
+    NiceSpinnerAdapter(
+            Context context,
+            List<T> items,
+            int backgroundSelector,
+            SpinnerTextFormatter spinnerTextFormatter,
+            PopUpTextAlignment horizontalAlignment
+    ) {
+        super(context, backgroundSelector, spinnerTextFormatter, horizontalAlignment);
+        this.items = items;
+    }
+
+    @Override
+    public int getCount() {
+        return items.size() - 1;
+    }
+
+    @Override
+    public T getItem(int position) {
+        if (position >= selectedIndex) {
+            return items.get(position + 1);
+        } else {
+            return items.get(position);
+        }
+    }
+
+    @Override
+    public T getItemInDataset(int position) {
+        return items.get(position);
+    }
+}

+ 50 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/NiceSpinnerAdapterWrapper.java

@@ -0,0 +1,50 @@
+package com.yingyang.workbenches.widget;
+
+import android.content.Context;
+import android.widget.ListAdapter;
+
+/*
+ * Copyright (C) 2015 Angelo Marchesin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class NiceSpinnerAdapterWrapper extends NiceSpinnerBaseAdapter {
+
+    private final ListAdapter baseAdapter;
+
+    NiceSpinnerAdapterWrapper(
+            Context context,
+            ListAdapter toWrap,
+            int backgroundSelector,
+            SpinnerTextFormatter spinnerTextFormatter,
+            PopUpTextAlignment horizontalAlignment
+    ) {
+        super(context, backgroundSelector, spinnerTextFormatter, horizontalAlignment);
+        baseAdapter = toWrap;
+    }
+
+    @Override
+    public int getCount() {
+        return baseAdapter.getCount() - 1;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return baseAdapter.getItem(position >= selectedIndex ? position + 1 : position);
+    }
+
+    @Override
+    public Object getItemInDataset(int position) {
+        return baseAdapter.getItem(position);
+    }
+}

+ 118 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/NiceSpinnerBaseAdapter.java

@@ -0,0 +1,118 @@
+package com.yingyang.workbenches.widget;
+
+import android.content.Context;
+import android.os.Build;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+import com.yingyang.workbenches.R;
+
+/*
+ * Copyright (C) 2015 Angelo Marchesin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@SuppressWarnings("unused")
+public abstract class NiceSpinnerBaseAdapter<T> extends BaseAdapter {
+
+    private final PopUpTextAlignment horizontalAlignment;
+    private final SpinnerTextFormatter spinnerTextFormatter;
+
+    private int backgroundSelector;
+
+    int selectedIndex;
+
+    NiceSpinnerBaseAdapter(
+            Context context,
+            int backgroundSelector,
+            SpinnerTextFormatter spinnerTextFormatter,
+            PopUpTextAlignment horizontalAlignment
+    ) {
+        this.spinnerTextFormatter = spinnerTextFormatter;
+        this.backgroundSelector = backgroundSelector;
+        this.horizontalAlignment = horizontalAlignment;
+    }
+
+    @Override
+    public View getView(int position, @Nullable View convertView, ViewGroup parent) {
+        Context context = parent.getContext();
+        TextView textView;
+
+        if (convertView == null) {
+            convertView = View.inflate(context, R.layout.spinner_list_item, null);
+            textView = convertView.findViewById(R.id.text_view_spinner);
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+                textView.setBackground(ContextCompat.getDrawable(context, backgroundSelector));
+            }
+            convertView.setTag(new ViewHolder(textView));
+        } else {
+            textView = ((ViewHolder) convertView.getTag()).textView;
+        }
+
+        textView.setText(spinnerTextFormatter.format(getItem(position)));
+        setTextHorizontalAlignment(textView);
+        return convertView;
+    }
+
+    private void setTextHorizontalAlignment(TextView textView) {
+        switch (horizontalAlignment) {
+            case START:
+                textView.setGravity(Gravity.START);
+                break;
+            case END:
+                textView.setGravity(Gravity.END);
+                break;
+            case CENTER:
+                textView.setGravity(Gravity.CENTER_HORIZONTAL);
+                break;
+            default:
+                break;
+        }
+    }
+
+    public int getSelectedIndex() {
+        return selectedIndex;
+    }
+
+    void setSelectedIndex(int index) {
+        selectedIndex = index;
+    }
+
+    public abstract T getItemInDataset(int position);
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public abstract T getItem(int position);
+
+    @Override
+    public abstract int getCount();
+
+    static class ViewHolder {
+        TextView textView;
+
+        ViewHolder(TextView textView) {
+            this.textView = textView;
+        }
+    }
+}

+ 7 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/OnSpinnerItemSelectedListener.java

@@ -0,0 +1,7 @@
+package com.yingyang.workbenches.widget;
+
+import android.view.View;
+
+public interface OnSpinnerItemSelectedListener {
+    void onItemSelected(NiceSpinner parent, View view, int position, long id);
+}

+ 20 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/PopUpTextAlignment.java

@@ -0,0 +1,20 @@
+package com.yingyang.workbenches.widget;
+
+enum PopUpTextAlignment {
+    START(0),
+    END(1),
+    CENTER(2);
+
+    private final int id;
+
+    PopUpTextAlignment(int id) {
+        this.id = id;
+    }
+
+    static PopUpTextAlignment fromId(int id) {
+        for (PopUpTextAlignment value : values()) {
+            if (value.id == id) return value;
+        }
+        return CENTER;
+    }
+}

+ 12 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/SimpleSpinnerTextFormatter.java

@@ -0,0 +1,12 @@
+package com.yingyang.workbenches.widget;
+
+import android.text.Spannable;
+import android.text.SpannableString;
+
+public class SimpleSpinnerTextFormatter implements SpinnerTextFormatter {
+
+    @Override
+    public Spannable format(Object item) {
+        return new SpannableString(item.toString());
+    }
+}

+ 8 - 0
workbenches/src/main/java/com/yingyang/workbenches/widget/SpinnerTextFormatter.java

@@ -0,0 +1,8 @@
+package com.yingyang.workbenches.widget;
+
+import android.text.Spannable;
+
+public interface SpinnerTextFormatter<T> {
+
+    Spannable format(T item);
+}

+ 5 - 0
workbenches/src/main/res/drawable/selector.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" tools:ignore="ResourceName">
+    <item android:drawable="@android:color/darker_gray" android:state_pressed="true" />
+    <item android:drawable="@android:color/white" android:state_pressed="false" />
+</selector>

+ 41 - 21
workbenches/src/main/res/layout/fragment_train_content.xml

@@ -13,22 +13,38 @@
         android:layout_height="match_parent">
 
         <androidx.constraintlayout.widget.ConstraintLayout
-            android:id="@+id/courselayout"
-            style="@style/training_content_title_layout"
-            android:layout_marginStart="@dimen/divider_78px"
-            android:layout_marginEnd="@dimen/divider_40px"
+            android:id="@+id/treatmentLayout"
+            android:layout_width="@dimen/divider_335px"
+            android:layout_height="@dimen/divider_62px"
+            android:layout_marginTop="@dimen/divider_60px"
             android:background="@drawable/bg_training_content"
-            tools:ignore="MissingConstraints">
-
-            <TextView
-                style="@style/training_content_title_textview"
-                android:text="第一个疗程"
+            android:gravity="center"
+            app:layout_constraintLeft_toLeftOf="parent"
+            app:layout_constraintRight_toRightOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <com.yingyang.workbenches.widget.NiceSpinner
+                android:id="@+id/treatmentSpinner"
+                android:layout_width="@dimen/divider_327px"
+                android:layout_height="@dimen/divider_54px"
+                android:paddingStart="@dimen/divider_32px"
+                android:textColor="@color/color_FF4773FF"
+                app:hideArrow="true"
+                android:gravity="center_horizontal"
+                app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintLeft_toLeftOf="parent"
-                tools:text="第一个疗程" />
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent"
+                tools:ignore="RtlSymmetry" />
 
             <androidx.appcompat.widget.AppCompatImageView
-                style="@style/training_content_title_arrow"
-                android:src="@mipmap/icon_arrow" />
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="@dimen/divider_13px"
+                android:src="@mipmap/icon_arrow_down"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
 
         </androidx.constraintlayout.widget.ConstraintLayout>
 
@@ -42,39 +58,43 @@
             android:background="@drawable/bg_training_content_title"
             app:layout_constraintLeft_toLeftOf="parent"
             app:layout_constraintRight_toRightOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/courselayout">
+            app:layout_constraintTop_toBottomOf="@+id/treatmentLayout">
 
-            <androidx.appcompat.widget.AppCompatTextView
+            <TextView
                 android:id="@+id/tvDate"
                 style="@style/training_content_title_appcompattextview"
                 android:text="@string/date"
                 app:layout_constraintHorizontal_weight="1"
                 app:layout_constraintLeft_toLeftOf="parent"
-                app:layout_constraintRight_toLeftOf="@id/tvExerciseTherapy" />
+                app:layout_constraintRight_toLeftOf="@id/tvExerciseTherapy"
+                tools:ignore="MissingConstraints" />
 
-            <androidx.appcompat.widget.AppCompatTextView
+            <TextView
                 android:id="@+id/tvExerciseTherapy"
                 style="@style/training_content_title_appcompattextview"
                 android:text="@string/exercise_therapy"
                 app:layout_constraintHorizontal_weight="1"
                 app:layout_constraintLeft_toRightOf="@id/tvDate"
-                app:layout_constraintRight_toLeftOf="@id/tvTrainingProgress" />
+                app:layout_constraintRight_toLeftOf="@id/tvTrainingProgress"
+                tools:ignore="MissingConstraints" />
 
-            <androidx.appcompat.widget.AppCompatTextView
+            <TextView
                 android:id="@+id/tvTrainingProgress"
                 style="@style/training_content_title_appcompattextview"
                 android:text="@string/training_progress"
                 app:layout_constraintHorizontal_weight="1"
                 app:layout_constraintLeft_toRightOf="@id/tvExerciseTherapy"
-                app:layout_constraintRight_toLeftOf="@id/tvCognitiveTraining" />
+                app:layout_constraintRight_toLeftOf="@id/tvCognitiveTraining"
+                tools:ignore="MissingConstraints" />
 
-            <androidx.appcompat.widget.AppCompatTextView
+            <TextView
                 android:id="@+id/tvCognitiveTraining"
                 style="@style/training_content_title_appcompattextview"
                 android:text="@string/cognitive_training"
                 app:layout_constraintHorizontal_weight="3"
                 app:layout_constraintLeft_toRightOf="@id/tvTrainingProgress"
-                app:layout_constraintRight_toRightOf="parent" />
+                app:layout_constraintRight_toRightOf="parent"
+                tools:ignore="MissingConstraints" />
 
         </androidx.constraintlayout.widget.ConstraintLayout>
 

+ 13 - 0
workbenches/src/main/res/layout/spinner_list_item.xml

@@ -0,0 +1,13 @@
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/text_view_spinner"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center"
+    android:ellipsize="marquee"
+    android:gravity="center"
+    android:singleLine="true"
+    android:textSize="@dimen/divider_36px"
+    tools:ignore="ResourceName"
+    tools:text="Item"
+    tools:textColor="@color/color_FF4A76FF" />

+ 17 - 0
workbenches/src/main/res/values/attrs.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <attr name="popupTextAlignment" format="enum" tools:ignore="ResourceName">
+        <enum name="start" value="0" />
+        <enum name="end" value="1" />
+        <enum name="center" value="2" />
+    </attr>
+
+    <declare-styleable name="NiceSpinner" tools:ignore="ResourceName">
+        <attr name="arrowTint" format="color" />
+        <attr name="hideArrow" format="boolean" />
+        <attr name="arrowDrawable" format="reference|color" />
+        <attr name="backgroundSelector" format="integer" />
+        <attr name="popupTextAlignment" />
+        <attr name="entries" format="reference" />
+    </declare-styleable>
+</resources>

+ 4 - 0
workbenches/src/main/res/values/dimens.xml

@@ -16,7 +16,11 @@
     <dimen name="divider_340px" tools:ignore="PxUsage">340px</dimen>
     <dimen name="divider_339px" tools:ignore="PxUsage">339px</dimen>
     <dimen name="divider_335px" tools:ignore="PxUsage">335px</dimen>
+    <dimen name="divider_333px" tools:ignore="PxUsage">333px</dimen>
+    <dimen name="divider_331px" tools:ignore="PxUsage">331px</dimen>
     <dimen name="divider_330px" tools:ignore="PxUsage">330px</dimen>
+    <dimen name="divider_329px" tools:ignore="PxUsage">329px</dimen>
+    <dimen name="divider_327px" tools:ignore="PxUsage">327px</dimen>
     <dimen name="divider_320px" tools:ignore="PxUsage">320px</dimen>
     <dimen name="divider_289px" tools:ignore="PxUsage">289px</dimen>
     <dimen name="divider_270px" tools:ignore="PxUsage">270px</dimen>