add optionpicker

This commit is contained in:
houzh 2023-03-21 02:53:46 +00:00
parent 6fc78ac680
commit c281bf55fa
7 changed files with 207 additions and 96 deletions

View File

@ -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{

View File

@ -1,29 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relativeLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#111111"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="10dp">
<NumberPicker
android:id="@+id/options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/text1"/>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<NumberPicker
android:id="@+id/numpicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/text1"/>
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/text2"
android:text="护理"/>
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"/>
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginVertical="5dp"
android:text="收藏"/>
</RelativeLayout>
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"/>
</merge>

View File

@ -3,34 +3,31 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="@+id/content"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
<OptionPicker
android:id="@+id/option1"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_above="@+id/optionsContainer"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:scaleType="center"
android:src="@mipmap/chenshan"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello world"
android:layout_gravity="right|center"/>
<NumberPicker
android:id="@+id/options"
android:layout_width="wrap_content"
android:layout_height="match_parent"
/>
</FrameLayout>
<LinearLayout
android:id="@+id/optionsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
</LinearLayout>
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="#112233"
android:text2="温度"
/>
<OptionPicker
android:id="@+id/option2"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/option1"
android:background="#332211"
android:text2="漂洗"
/>
<OptionPicker
android:id="@+id/option3"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@id/option2"
android:text2="转速"
/>
</RelativeLayout>

View File

@ -8,10 +8,11 @@
<id name="often">0x00002715</id>
<id name="care">0x00002716</id>
<id name="favorite">0x00002717</id>
<id name="options">0x00002718</id>
<id name="numpicker">0x00002718</id>
<id name="text1">0x00002719</id>
<id name="text2">0x0000271a</id>
<id name="content">0x0000271b</id>
<id name="optionsContainer">0x0000271c</id>
<id name="option1">0x0000271b</id>
<id name="option2">0x0000271c</id>
<id name="option3">0x0000271d</id>
</resources>

110
apps/w9/optionpicker.cc Normal file
View File

@ -0,0 +1,110 @@
#include <optionpicker.h>
#include <cdtypes.h>
#include <cdlog.h>
#include <R.h>
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<mValues.size()&&ov>=0) ov=mValues.at(ov);
if(nv<mValues.size()&&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<int>&values,const std::vector<std::string>&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);
}

27
apps/w9/optionpicker.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include <widget/relativelayout.h>
#include <widget/numberpicker.h>
#include <widget/textview.h>
class OptionPicker:public RelativeLayout{
protected:
NumberPicker*mNumberPicker;
TextView* mText1,*mText2;
std::vector<int>mValues;
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<int>&values,const std::vector<std::string>&names);
void showOptions(bool on);
};

View File

@ -1,47 +1,21 @@
#include <washoptions.h>
#include <cdroid.h>
#include <R.h>
#include <optionpicker.h>
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;i<count;i++){
ToggleButton*opt=new ToggleButton(100,100);
ll->addView(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<ViewGroup*>(getChildAt(0));
for(int i=0;i<vg->getChildCount();i++){
vg->getChildAt(i)->setOnClickListener(std::bind(&WashOptionsWindow::onOptionClick,this,std::placeholders::_1));
}
dynamic_cast<FrameLayout::LayoutParams*>(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<ToggleButton&>(v).isChecked();
for(int i=0;i<count;i++){
View*v=parent->getChildAt(i);
dynamic_cast<ToggleButton*>(v)->setChecked(false);
ViewGroup*vg=v.getParent();
for(int i=0;i<vg->getChildCount();i++){
OptionPicker*op=dynamic_cast<OptionPicker*>(vg->getChildAt(i));
op->showOptions(op==&v);
}
dynamic_cast<ToggleButton&>(v).setChecked(checked);
NumberPicker*np=(NumberPicker*)findViewById(w9::R::id::options);
dynamic_cast<FrameLayout::LayoutParams*>(np->getLayoutParams())->setMarginStart(v.getLeft());
FrameLayout*frame=(FrameLayout*)findViewById(w9::R::id::content);
LOGD("set numberpicker to %d",v.getLeft());
frame->requestLayout();
invalidate();
}