From 01ff092f7b281c49135b5abd34082110c83d3316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=AF=E6=AD=8C?= Date: Tue, 12 Oct 2021 13:40:38 +0800 Subject: [PATCH] modify numberpicker,add longclick's auto increment/decrement support --- apps/samples/numpicker1.cc | 20 ++++++ src/gui/widget/numberpicker.cc | 126 ++++++++++++++++++++++++++++----- src/gui/widget/numberpicker.h | 18 ++++- 3 files changed, 145 insertions(+), 19 deletions(-) create mode 100755 apps/samples/numpicker1.cc diff --git a/apps/samples/numpicker1.cc b/apps/samples/numpicker1.cc new file mode 100755 index 00000000..e2b36069 --- /dev/null +++ b/apps/samples/numpicker1.cc @@ -0,0 +1,20 @@ +#include + +int main(int argc,const char*argv[]){ + App app(argc,argv); + Window*w=new Window(0,0,1280,600); + + LinearLayout*layout=new LinearLayout(1280,600); + layout->setOrientation(LinearLayout::VERTICAL); + + NumberPicker*np1=new NumberPicker(200,80); + np1->setMinValue(1); + np1->setMaxValue(12); + np1->setMinHeight(80); + np1->setBackgroundColor(0xFF111111); + + layout->addView(np1); + w->addView(layout); + w->requestLayout(); + app.exec(); +} diff --git a/src/gui/widget/numberpicker.cc b/src/gui/widget/numberpicker.cc index 6900228c..bc44f292 100755 --- a/src/gui/widget/numberpicker.cc +++ b/src/gui/widget/numberpicker.cc @@ -10,21 +10,27 @@ namespace cdroid{ NumberPicker::NumberPicker(int w,int h):LinearLayout(w,h){ initView(); setOrientation(VERTICAL);//HORIZONTAL); - - /*mDecrementButton=new ImageButton(30,20); - addView(mDecrementButton,new LayoutParams(LayoutParams::WRAP_CONTENT,LayoutParams::WRAP_CONTENT)); - mDecrementButton->setOnClickListener(std::bind(&NumberPicker::onIncDecClick,this,std::placeholders::_1)); - mDecrementButton->setOnLongClickListener(std::bind(&NumberPicker::onIncDecLongClick,this,std::placeholders::_1));*/ + + if(!mHasSelectorWheel){ + mDecrementButton=new ImageButton(30,20); + mDecrementButton->setMinimumHeight(20); + addView(mDecrementButton,new LayoutParams(LayoutParams::WRAP_CONTENT,LayoutParams::WRAP_CONTENT)); + mDecrementButton->setOnClickListener(std::bind(&NumberPicker::onIncDecClick,this,std::placeholders::_1)); + mDecrementButton->setOnLongClickListener(std::bind(&NumberPicker::onIncDecLongClick,this,std::placeholders::_1)); + } mInputText =new EditText("123",20,20); mInputText->setGravity(Gravity::CENTER); mInputText->setTextSize(24); addView(mInputText,new LayoutParams(LayoutParams::MATCH_PARENT,LayoutParams::WRAP_CONTENT)); - /*mIncrementButton=new ImageButton(30,20); - addView(mIncrementButton,new LayoutParams(LayoutParams::WRAP_CONTENT,LayoutParams::WRAP_CONTENT)); - mIncrementButton->setOnClickListener(std::bind(&NumberPicker::onIncDecClick,this,std::placeholders::_1)); - mIncrementButton->setOnLongClickListener(std::bind(&NumberPicker::onIncDecLongClick,this,std::placeholders::_1));*/ + if(!mHasSelectorWheel){ + mIncrementButton=new ImageButton(30,20); + mIncrementButton->setMinimumHeight(20); + addView(mIncrementButton,new LayoutParams(LayoutParams::WRAP_CONTENT,LayoutParams::WRAP_CONTENT)); + mIncrementButton->setOnClickListener(std::bind(&NumberPicker::onIncDecClick,this,std::placeholders::_1)); + mIncrementButton->setOnLongClickListener(std::bind(&NumberPicker::onIncDecLongClick,this,std::placeholders::_1)); + } } NumberPicker::NumberPicker(Context* context,const AttributeSet& atts):LinearLayout(context,atts){ @@ -81,6 +87,7 @@ NumberPicker::NumberPicker(Context* context,const AttributeSet& atts):LinearLayo void NumberPicker::onIncDecClick(View&v){ hideSoftInput(); + LOGD("onclick %p",&v); mInputText->clearFocus(); if (&v == mIncrementButton) { changeValueByOne(true); @@ -115,8 +122,13 @@ void NumberPicker::initView(){ mVirtualButtonPressedDrawable =nullptr; mLastHandledDownDpadKeyCode =-1; mHasSelectorWheel = true; + mWrapSelectorWheel= false; mWrapSelectorWheelPreferred =true; mSelectionDividerHeight =1; + mPreviousScrollerY =0; + mCurrentScrollOffset =0; + mInitialScrollOffset =0; + mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; mMinHeight = SIZE_UNSPECIFIED; mMaxHeight = SIZE_UNSPECIFIED; mMinWidth = SIZE_UNSPECIFIED; @@ -210,16 +222,16 @@ bool NumberPicker::onInterceptTouchEvent(MotionEvent& event){ hideSoftInput(); mLastDownOrMoveEventY = mLastDownEventY = event.getY(); mLastDownEventTime = event.getEventTime(); - mIgnoreMoveEvents = false; + mIgnoreMoveEvents = false; mPerformClickOnTap = false; // Handle pressed state before any state change. if (mLastDownEventY < mTopSelectionDividerTop) { if (mScrollState == OnScrollListener::SCROLL_STATE_IDLE) { - //mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_DECREMENT); + pshButtonPressDelayed(BUTTON_DECREMENT); } } else if (mLastDownEventY > mBottomSelectionDividerBottom) { if (mScrollState == OnScrollListener::SCROLL_STATE_IDLE) { - //mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_INCREMENT); + pshButtonPressDelayed(BUTTON_INCREMENT); } } // Make sure we support flinging inside scrollables. @@ -277,7 +289,7 @@ bool NumberPicker::onTouchEvent(MotionEvent& event){ case MotionEvent::ACTION_UP: { removeBeginSoftInputCommand(); removeChangeCurrentByOneFromLongPress(); - //mPressedStateHelper.cancel(); + pshCancel();//mPressedStateHelper.cancel(); //VelocityTracker* velocityTracker = mVelocityTracker; mVelocityTracker->computeCurrentVelocity(1000, mMaximumFlingVelocity); int initialVelocity = (int) mVelocityTracker->getYVelocity(); @@ -298,10 +310,10 @@ bool NumberPicker::onTouchEvent(MotionEvent& event){ - SELECTOR_MIDDLE_ITEM_INDEX; if (selectorIndexOffset > 0) { changeValueByOne(true); - //mPressedStateHelper.buttonTapped(PressedStateHelper.BUTTON_INCREMENT); + pshButtonTapped(BUTTON_INCREMENT); } else if (selectorIndexOffset < 0) { changeValueByOne(false); - //mPressedStateHelper.buttonTapped(PressedStateHelper.BUTTON_DECREMENT); + pshButtonTapped(BUTTON_DECREMENT); } } } else { @@ -715,7 +727,7 @@ void NumberPicker::setValueInternal(int current, bool notifyChng){ } void NumberPicker::changeValueByOne(bool increment){ - LOGD("mHasSelectorWheel=%d",mHasSelectorWheel); + LOGV("mHasSelectorWheel=%d",mHasSelectorWheel); if (mHasSelectorWheel) { hideSoftInput(); if (!moveToFinalScrollerPosition(mFlingScroller)) { @@ -873,19 +885,32 @@ void NumberPicker::notifyChange(int previous, int current){ } void NumberPicker::postChangeCurrentByOneFromLongPress(bool increment, long delayMillis){ + if(mChangeCurrentByOneFromLongPressCommand!=nullptr) + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); + mChangeCurrentByOneFromLongPressCommand=[this,increment](){ + changeValueByOne(increment); + postDelayed(mChangeCurrentByOneFromLongPressCommand, mLongPressUpdateInterval); + }; + postDelayed(mChangeCurrentByOneFromLongPressCommand, delayMillis); } void NumberPicker::removeChangeCurrentByOneFromLongPress(){ - /*if (mChangeCurrentByOneFromLongPressCommand != nullptr) { + if (mChangeCurrentByOneFromLongPressCommand != nullptr) { removeCallbacks(mChangeCurrentByOneFromLongPressCommand); - }*/ + mChangeCurrentByOneFromLongPressCommand =nullptr; + } } void NumberPicker::removeBeginSoftInputCommand(){ } void NumberPicker::removeAllCallbacks(){ + if (mChangeCurrentByOneFromLongPressCommand != nullptr) { + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); + mChangeCurrentByOneFromLongPressCommand =nullptr; + } + pshCancel(); } int NumberPicker::getSelectedPos(const std::string& value){ @@ -919,4 +944,69 @@ bool NumberPicker::ensureScrollWheelAdjusted() { } return false; } + +void NumberPicker::pshCancel(){ + mPSHMode =0; + mPSHManagedButton=0; + if(mPressedStateHelpers!=nullptr){ + removeCallbacks(mPressedStateHelpers); + invalidate(0, mBottomSelectionDividerBottom, mRight-mLeft, mBottom-mTop); + } + mPressedStateHelpers =[this](){ + pshRun(); + }; + mDecrementVirtualButtonPressed =false; + if(mDecrementVirtualButtonPressed) + invalidate(0,0,mRight-mLeft,mTopSelectionDividerTop); +} + +void NumberPicker::pshButtonPressDelayed(int button){ + pshCancel(); + mPSHMode =MODE_PRESS; + mPSHManagedButton =button; + + postDelayed(mPressedStateHelpers,ViewConfiguration::getTapTimeout()); +} + +void NumberPicker::pshButtonTapped(int button){ + pshCancel(); + mPSHMode =MODE_TAPPED; + mPSHManagedButton=button; + post(mPressedStateHelpers); +} + +void NumberPicker::pshRun(){ + switch (mPSHMode) { + case MODE_PRESS: + switch (mPSHManagedButton) { + case BUTTON_INCREMENT: + mIncrementVirtualButtonPressed = true; + invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); + break; + case BUTTON_DECREMENT: + mDecrementVirtualButtonPressed = true; + invalidate(0, 0, mRight, mTopSelectionDividerTop); + break; + } + break; + case MODE_TAPPED: + switch (mPSHManagedButton) { + case BUTTON_INCREMENT: + if (!mIncrementVirtualButtonPressed) { + postDelayed(mPressedStateHelpers,ViewConfiguration::getPressedStateDuration()); + } + mIncrementVirtualButtonPressed ^= true; + invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); + break; + case BUTTON_DECREMENT: + if (!mDecrementVirtualButtonPressed) { + postDelayed(mPressedStateHelpers,ViewConfiguration::getPressedStateDuration()); + } + mDecrementVirtualButtonPressed ^= true; + invalidate(0, 0, mRight, mTopSelectionDividerTop); + }//endof switch (mManagedButton) + break;/*endof case MODE_TAPPED*/ + } +} + }//namespace diff --git a/src/gui/widget/numberpicker.h b/src/gui/widget/numberpicker.h index 81d0bb24..f2eb307c 100755 --- a/src/gui/widget/numberpicker.h +++ b/src/gui/widget/numberpicker.h @@ -20,7 +20,12 @@ public: std::functiononScrollStateChange; }; private: + static constexpr int BUTTON_INCREMENT =1; + static constexpr int BUTTON_DECREMENT =2; + static constexpr int MODE_PRESS =1; + static constexpr int MODE_TAPPED=2; static constexpr int SELECTOR_WHEEL_ITEM_COUNT =3; + static constexpr int DEFAULT_LONG_PRESS_UPDATE_INTERVAL =300; static constexpr int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; static constexpr int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT =8; static constexpr int SELECTOR_ADJUSTMENT_DURATION_MILLIS =800; @@ -32,6 +37,7 @@ private: ImageButton* mIncrementButton; ImageButton* mDecrementButton; EditText* mInputText; + Runnable mChangeCurrentByOneFromLongPressCommand; int mSelectionDividersDistance; int mMinHeight; int mMaxHeight; @@ -80,6 +86,16 @@ private: int mLastHandledDownDpadKeyCode = -1; bool mHideWheelUntilFocused; bool mWrapSelectorWheelPreferred=true; + + + //PressedStateHelper's members + Runnable mPressedStateHelpers; + int mPSHManagedButton; + int mPSHMode; + void pshCancel(); + void pshButtonPressDelayed(int); + void pshButtonTapped(int); + void pshRun(); private: void initView(); int makeMeasureSpec(int measureSpec, int maxSize); @@ -129,7 +145,7 @@ public: bool onTouchEvent(MotionEvent& event)override; bool dispatchTouchEvent(MotionEvent& event)override; bool dispatchKeyEvent(KeyEvent& event)override; - void computeScroll(); + void computeScroll()override; View& setEnabled(bool enabled)override; void scrollBy(int x, int y)override; int getSolidColor()const;