首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android WheelView 與 EditText 雙向聯動實現:防死循環的最佳實踐

     編輯:程式設計疑難解答

業務場景

金額輸入頁:上方 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;
            }
        });
    }
}

關鍵點總結

  1. 單向觸發源:只有用戶交互結束時(Selected / afterTextChanged)才觸發同步。
  2. 程序化標誌位:isProgrammatic 阻斷代碼設置值時的回調。
  3. 格式規範化:輸入框實時校驗小數位、上限、前導零,保證數據幹淨。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved