diff --git a/apps/w9/R.h b/apps/w9/R.h index 7897a4b5..d566822b 100644 --- a/apps/w9/R.h +++ b/apps/w9/R.h @@ -14,11 +14,12 @@ namespace R{ static constexpr int often = 0x00002715 ;/*10005*/ static constexpr int care = 0x00002716 ;/*10006*/ static constexpr int favorite = 0x00002717 ;/*10007*/ - static constexpr int options = 0x00002718 ;/*10008*/ + static constexpr int numpicker = 0x00002718 ;/*10008*/ static constexpr int text1 = 0x00002719 ;/*10009*/ static constexpr int text2 = 0x0000271A ;/*10010*/ - static constexpr int content = 0x0000271B ;/*10011*/ - static constexpr int optionsContainer = 0x0000271C ;/*10012*/ + static constexpr int option1 = 0x0000271B ;/*10011*/ + static constexpr int option2 = 0x0000271C ;/*10012*/ + static constexpr int option3 = 0x0000271D ;/*10013*/ };/*namespace id*/ namespace strings{ diff --git a/apps/w9/assets/layout/optionitem.xml b/apps/w9/assets/layout/optionitem.xml index 8d811809..69591877 100755 --- a/apps/w9/assets/layout/optionitem.xml +++ b/apps/w9/assets/layout/optionitem.xml @@ -1,29 +1,30 @@ - - + + + android:id="@+id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="1dp" + android:layout_above="@id/text2" + android:gravity="center" + android:textSize="32dp" + android:textColor="white" + android:paddingVertical="5dp" + android:background="#121212"/> - + android:id="@+id/text2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_marginTop="1dp" + android:paddingVertical="5dp" + android:gravity="center" + android:textSize="32dp" + android:background="#181818"/> + diff --git a/apps/w9/assets/layout/options.xml b/apps/w9/assets/layout/options.xml index c867ab1d..db6b1887 100755 --- a/apps/w9/assets/layout/options.xml +++ b/apps/w9/assets/layout/options.xml @@ -3,34 +3,31 @@ android:layout_width="match_parent" android:layout_height="match_parent" > - - - - - - - + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:background="#112233" + android:text2="温度" + /> + + diff --git a/apps/w9/assets/values/ID.xml b/apps/w9/assets/values/ID.xml index a7f5ac82..6334fd20 100644 --- a/apps/w9/assets/values/ID.xml +++ b/apps/w9/assets/values/ID.xml @@ -8,10 +8,11 @@ 0x00002715 0x00002716 0x00002717 - 0x00002718 + 0x00002718 0x00002719 0x0000271a - 0x0000271b - 0x0000271c + 0x0000271b + 0x0000271c + 0x0000271d diff --git a/apps/w9/optionpicker.cc b/apps/w9/optionpicker.cc new file mode 100644 index 00000000..d760210a --- /dev/null +++ b/apps/w9/optionpicker.cc @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +DECLARE_WIDGET(OptionPicker) +OptionPicker::OptionPicker(int w,int h):RelativeLayout(w,h){ + +} + +OptionPicker::OptionPicker(Context*ctx,const AttributeSet&attr):RelativeLayout(ctx,attr){ + LayoutInflater::from(ctx)->inflate("@layout/optionitem",this); + mNumberPicker = (NumberPicker*)findViewById(w9::R::id::numpicker); + mNumberPicker->setVisibility(View::GONE); + mText1=(TextView*)findViewById(w9::R::id::text1); + mText2=(TextView*)findViewById(w9::R::id::text2); + mText1->setText(attr.getString("text1")); + mText2->setText(attr.getString("text2")); + LOGD("mNumberPicker=%p text=%p/%p",mNumberPicker,mText1,mText2); + mNumberPicker->setOnValueChangedListener([this](NumberPicker&v,int ov,int nv){ + mText1->setText(std::to_string(nv)); + if(ov=0) ov=mValues.at(ov); + if(nv=0) nv=mValues.at(nv); + if(mOnValueChangedListener) + mOnValueChangedListener(v,ov,nv); + }); +} + +NumberPicker&OptionPicker::getPicker(){ + return *mNumberPicker; +} + +void OptionPicker::setText(const std::string&text){ + mText1->setText(text); +} + +void OptionPicker::setText(const std::string&text1,const std::string&text2){ + mText1->setText(text1); + mText2->setText(text2); +} + +void OptionPicker::setOnValueChangedListener(NumberPicker::OnValueChangeListener onValueChangedListener){ + mOnValueChangedListener=onValueChangedListener; +} + +void OptionPicker::setValuedName(const std::vector&values,const std::vector&names){ + mValues=values; + mNumberPicker->setMinValue(0); + mNumberPicker->setMaxValue(values.size()); + mNumberPicker->setDisplayedValues(names); +} + +void OptionPicker::showOptions(bool on){ + mNumberPicker->setVisibility(on?View::VISIBLE:View::GONE); + LOGV("%p:%d visible=%d",this,mID,on); +} + +static int makeMeasureSpec(int measureSpec, int maxSize){ + if (maxSize == -1/*SIZE_UNSPECIFIED*/) { + return measureSpec; + } + int size = MeasureSpec::getSize(measureSpec); + int mode = MeasureSpec::getMode(measureSpec); + switch (mode) { + case MeasureSpec::EXACTLY: return measureSpec; + case MeasureSpec::AT_MOST: return MeasureSpec::makeMeasureSpec(std::min(size, maxSize), MeasureSpec::EXACTLY); + case MeasureSpec::UNSPECIFIED: return MeasureSpec::makeMeasureSpec(maxSize, MeasureSpec::EXACTLY); + default: throw std::string("Unknown measure mode: ")+std::to_string(mode); + } +} + +int OptionPicker::resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize, int measureSpec) { + if (minSize != -1/*SIZE_UNSPECIFIED*/) { + int desiredWidth = std::max(minSize, measuredSize); + return resolveSizeAndState(desiredWidth, measureSpec, 0); + } else { + return measuredSize; + } +} + +void OptionPicker::onMeasure(int widthMeasureSpec, int heightMeasureSpec){ + RelativeLayout::onMeasure(widthMeasureSpec,heightMeasureSpec); + return; + // Try greedily to fit the max width and height. + const int mMaxWidth=-1, mMaxHeight=-1; + const int mMinWidth=-1, mMinHeight=-1; + int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth); + int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight); + RelativeLayout::onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); + // Flag if we are measured with width or height less than the respective min. + int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(), + widthMeasureSpec); + int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(), + heightMeasureSpec); + LOGD("%p:%d setMeasuredDimension(%x/%d,%x/%d)",this,mID,widthSize,widthSize,heightSize,heightSize); + setMeasuredDimension(widthSize, heightSize); +} + +void OptionPicker::onLayout(bool changed, int left, int top, int width, int height){ + RelativeLayout::onLayout(changed,left,top,width,height); + return ; + const int inptTxtMsrdWdth = mText2->getMeasuredWidth(); + const int inptTxtMsrdHght = mText2->getMeasuredHeight(); + const int msrdWdth = getMeasuredWidth(); + const int msrdHght = getMeasuredHeight(); + mText2->layout(0, msrdHght-inptTxtMsrdHght, inptTxtMsrdWdth, inptTxtMsrdHght); + mText1->layout(0,msrdHght-inptTxtMsrdHght*2,inptTxtMsrdWdth, inptTxtMsrdHght); + LOGD("%p:%d textSize=(%d,%d) measuredsize=%dx%d",this,mID,inptTxtMsrdWdth,inptTxtMsrdHght,msrdWdth,msrdHght); + mNumberPicker->layout(0,0,inptTxtMsrdWdth,msrdHght-inptTxtMsrdHght*2); +} diff --git a/apps/w9/optionpicker.h b/apps/w9/optionpicker.h new file mode 100644 index 00000000..7e0ebb06 --- /dev/null +++ b/apps/w9/optionpicker.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +#include + +class OptionPicker:public RelativeLayout{ +protected: + NumberPicker*mNumberPicker; + TextView* mText1,*mText2; + std::vectormValues; + NumberPicker::OnValueChangeListener mOnValueChangedListener; +protected: + int resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize, int measureSpec); + void onMeasure(int widthMeasureSpec, int heightMeasureSpec)override; + void onLayout(bool changed, int left, int top, int width, int height)override; +public: + OptionPicker(int,int); + OptionPicker(Context*,const AttributeSet&attr); + NumberPicker&getPicker(); + void setText(const std::string&text); + void setText(const std::string&,const std::string&); + void setOnValueChangedListener(NumberPicker::OnValueChangeListener onValueChangedListener); + /*values used for uart commandid,names used for display,values.size==names.size*/ + void setValuedName(const std::vector&values,const std::vector&names); + void showOptions(bool on); +}; + diff --git a/apps/w9/washoptions.cc b/apps/w9/washoptions.cc index bbaed117..506b9245 100644 --- a/apps/w9/washoptions.cc +++ b/apps/w9/washoptions.cc @@ -1,47 +1,21 @@ #include #include #include +#include -WashOptionsWindow::WashOptionsWindow(int options):Window(0,0,1280,800){ +WashOptionsWindow::WashOptionsWindow(int options):Window(0,0,-1,-1){ LayoutInflater::from(getContext())->inflate("@layout/options",this); - NumberPicker*np=(NumberPicker*)findViewById(w9::R::id::options); - np->setMinValue(0); - np->setMaxValue(4); - np->setSelector(5,-1); - LinearLayout*ll=(LinearLayout*)findViewById(w9::R::id::optionsContainer); - const char*labels[]={ - "Button0", - "Button1", - "Button2", - "Button3", - "Button4", - "Button5" - }; - const int count=sizeof(labels)/sizeof(labels[0]); - for(int i=0;iaddView(opt,new LinearLayout::LayoutParams(-1,32,1.f/count)).setId(100+i).setClickable(true); - opt->setText(labels[i]); - opt->setBackgroundResource("@drawable/optionbackground"); - opt->setOnClickListener(std::bind(&WashOptionsWindow::onOptionClick,this,std::placeholders::_1)); + ViewGroup*vg=dynamic_cast(getChildAt(0)); + for(int i=0;igetChildCount();i++){ + vg->getChildAt(i)->setOnClickListener(std::bind(&WashOptionsWindow::onOptionClick,this,std::placeholders::_1)); } - dynamic_cast(np->getLayoutParams())->setMarginStart(600); - FrameLayout*frame=(FrameLayout*)findViewById(w9::R::id::content); - frame->requestLayout(); } void WashOptionsWindow::onOptionClick(View&v){ - ViewGroup*parent=v.getParent(); - const int count=parent->getChildCount(); - const bool checked=dynamic_cast(v).isChecked(); - for(int i=0;igetChildAt(i); - dynamic_cast(v)->setChecked(false); + ViewGroup*vg=v.getParent(); + for(int i=0;igetChildCount();i++){ + OptionPicker*op=dynamic_cast(vg->getChildAt(i)); + op->showOptions(op==&v); } - dynamic_cast(v).setChecked(checked); - NumberPicker*np=(NumberPicker*)findViewById(w9::R::id::options); - dynamic_cast(np->getLayoutParams())->setMarginStart(v.getLeft()); - FrameLayout*frame=(FrameLayout*)findViewById(w9::R::id::content); - LOGD("set numberpicker to %d",v.getLeft()); - frame->requestLayout(); + invalidate(); }