Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

android - How to delete and moveback to previous passcode box?

i'm developing some apps that use One-time password. The problem I face is, when the box is not filled(6th box), when I press the delete key, the cursor doesn't return to the previous box. The problem doesn't happen when 6 boxes are filled and I press the delete button. The cursor clears the contents and moves back to the previous box. How can I make it move to previous box when I press delete button on empty box?

Passcode

Here's some of my code

PasscodeTextField(
   onTextChanged: (passcode) {
      setState(() {
         checkCode(passcode);
      });
      print(passcode);
   },
   totalCharacters: 6,
   passcodeType: PasscodeType.number,
)

passcodehelper.dart

library passcode;

import 'package:flutter/material.dart';

typedef Null PasscodeChangedCallback(String passcode);
typedef Null BlockTextChangedCallback(String blockText, int blockPosition);

enum PasscodeType {
  number,
  alphaNumeric,
}

class PasscodeTextField extends StatefulWidget {
  final int totalCharacters;
  final PasscodeType passcodeType;
  final PasscodeChangedCallback onTextChanged;
  final Size size;
  final Color backgroundColor;
  final Color borderColor;
  final Color textColor;
  final bool obscureText;

  PasscodeTextField({
    @required this.totalCharacters,
    this.passcodeType = PasscodeType.alphaNumeric,
    @required this.onTextChanged,
    this.size,
    this.backgroundColor = Colors.white,
    this.borderColor = Colors.transparent,
    this.textColor = Colors.black,
    this.obscureText = false,
  }) : assert(totalCharacters <= 10);

  @override
  _PasscodeTextFieldState createState() => _PasscodeTextFieldState();
}

class _PasscodeTextFieldState extends State<PasscodeTextField> {
  List<FocusNode> focusNodes;
  Map<int, String> passcode = {};

  @override
  void initState() {
    super.initState();
    focusNodes = List.generate(widget.totalCharacters, (int n) {
      return FocusNode();
    });
  }

  @override
  Widget build(BuildContext context) {
    double widthSize = 1.0;
    double heightSize = 1.0;

    if (widget.size != null) {
      widthSize = widget.size.width / widget.totalCharacters;
      heightSize = widget.size.height;
    }

    return Container(
      width: widget.size?.width ?? null,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: List.generate(widget.totalCharacters, (index) {
          return TextFieldBox(
            widget.size != null
                ? (widthSize > heightSize ? heightSize : widthSize)
                : 50.0,
            (blockText, blockPosition) {
              if (blockText == "") {
                if (blockPosition > 0) {
                  FocusScope.of(context)
                      .requestFocus(focusNodes[blockPosition - 1]);
                }
              } else if (blockPosition < focusNodes.length - 1) {
                FocusScope.of(context)
                    .requestFocus(focusNodes[blockPosition + 1]);
              }
              if (blockText == "") {
                passcode[blockPosition] = null;
              } else {
                passcode[blockPosition] = blockText;
              }
              String currentPasscode = "";
              for (int i = 0; i < widget.totalCharacters; i++) {
                currentPasscode += passcode[i];
              }
              widget.onTextChanged(currentPasscode);
            },
            widget.passcodeType,
            index,
            focusNodes[index],
            widget.backgroundColor,
            widget.borderColor,
            widget.totalCharacters,
            widget.textColor,
            widget.obscureText,
          );
        }),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    focusNodes.forEach((node) {
      node.dispose();
    });
  }
}

class TextFieldBox extends StatefulWidget {
  final double size;
  final BlockTextChangedCallback onBlockTextChanged;
  final PasscodeType passcodeType;
  final int boxPosition;
  final FocusNode focusNode;
  final Color backgroundColor;
  final Color borderColor;
  final int totalCharacters;
  final Color textColor;
  final bool obscureText;

  TextFieldBox(
    this.size,
    this.onBlockTextChanged,
    this.passcodeType,
    this.boxPosition,
    this.focusNode,
    this.backgroundColor,
    this.borderColor,
    this.totalCharacters,
    this.textColor,
    this.obscureText,
  );

  @override
  _TextFieldBoxState createState() => _TextFieldBoxState();
}

class _TextFieldBoxState extends State<TextFieldBox> {
  TextEditingController controller;
  String previousText = "";

  @override
  void initState() {
    super.initState();
    controller = TextEditingController();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: widget.size,
      width: widget.size,
      child: Card(
        shape: RoundedRectangleBorder(
          side: BorderSide(
            color: widget.borderColor ?? Colors.transparent,
          ),
        ),
        color: widget.backgroundColor,
        child: Padding(
          padding: const EdgeInsets.all(2.0),
          child: Center(
            child: Row(
              children: <Widget>[
                Expanded(
                  child: TextField(
                    textAlign: TextAlign.center,
                    controller: controller,
                    obscureText: widget.obscureText,
                    focusNode: widget.focusNode,
                    style: TextStyle(
                        color: widget.textColor ?? Colors.black,
                        fontSize: widget.size * 0.4),
                    decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: '',
                      counterStyle: TextStyle(
                        color: Colors.transparent,
                      ),
                    ),
                    keyboardType: _getKeyboardType(widget.passcodeType),
                    onChanged: (value) {
                      if (value == "") {
                        widget.onBlockTextChanged("", widget.boxPosition);
                      } else {
                        controller.text = value[value.length - 1];
                        widget.onBlockTextChanged(
                            value[value.length - 1], widget.boxPosition);
                      }
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  TextInputType _getKeyboardType(PasscodeType type) {
    switch (type) {
      case PasscodeType.alphaNumeric:
        return TextInputType.text;
      case PasscodeType.number:
        return TextInputType.number;
      default:
        return TextInputType.text;
    }
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...