金額輸入頁:上方 WheelView 滾動選擇金額(步長 100),下方 EditText 手動輸入。要求雙向同步,且避免「滾動觸發輸入 → 輸入觸發滾動」的死循環。
WheelView:使用 OnWheelItemSelectedListener(手指抬起、滾動停穩)而非 OnWheelItemChangedListener(滾動中每幀)。EditText:在 afterTextChanged 中更新 WheelView,但需加鎖標誌位防止遞歸。public class MainActivity extends AppCompatActivity {
private WheelView mWheelView;
private EditText mMoneyEt;
private final int unitValue = 100;
private final int maxValue = 100000;
private boolean isProgrammatic = false; // 防遞歸標誌
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWheelView = findViewById(R.id.wheelview);
mMoneyEt = findViewById(R.id.et_money);
// 初始化 WheelView 數據
List<String> items = new ArrayList<>();
for (int i = 0; i <= maxValue / unitValue; i++) {
items.add(String.valueOf(i * unitValue));
}
mWheelView.setItems(items);
mWheelView.selectIndex(0);
// WheelView → EditText
mWheelView.setOnWheelItemSelectedListener(new WheelView.OnWheelItemSelectedListener() {
@Override public void onWheelItemSelected(WheelView wheelView, int position) {
if (isProgrammatic) return;
String val = wheelView.getItems().get(position);
mMoneyEt.setText(val);
}
@Override public void onWheelItemChanged(WheelView wheelView, int position) { }
});
// EditText → WheelView
addPriceWatcher(mMoneyEt, maxValue);
}
private void addPriceWatcher(EditText et, float max) {
et.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
// 格式校驗:小數點後最多 2 位、不超過上限、首位不為 0 等
// ...(省略具體校驗邏輯,參考原答案)
}
@Override public void afterTextChanged(Editable s) {
if (isProgrammatic || TextUtils.isEmpty(s)) return;
float value = Float.parseFloat(s.toString());
int pos = Math.min((int)(value / unitValue), max / unitValue);
isProgrammatic = true;
mWheelView.selectIndex(pos);
isProgrammatic = false;
}
});
}
}
isProgrammatic 阻斷代碼設置值時的回調。