Skip to content

Commit b7c917b

Browse files
committed
Custom TextField
1 parent 9045b32 commit b7c917b

1 file changed

Lines changed: 120 additions & 0 deletions

File tree

lib/code_judge_edit_text.dart

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/// Copyright 2026 Fabian Roland (naibaf-1)
2+
3+
/// Licensed under the Apache License, Version 2.0 (the "License");
4+
/// you may not use this file except in compliance with the License.
5+
/// You may obtain a copy of the License at
6+
7+
/// http://www.apache.org/licenses/LICENSE-2.0
8+
9+
/// Unless required by applicable law or agreed to in writing, software
10+
/// distributed under the License is distributed on an "AS IS" BASIS,
11+
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
/// See the License for the specific language governing permissions and
13+
/// limitations under the License.
14+
library;
15+
16+
import 'package:flutter/material.dart';
17+
18+
// Customised TextField
19+
class CodeJudgeEditText extends StatefulWidget {
20+
final bool multiline;
21+
final bool autocorrect;
22+
final bool suggestions;
23+
final bool autofocus;
24+
final TextInputType textInputType;
25+
final String hint;
26+
final ValueChanged<String>? onInputDone;
27+
final String? text;
28+
29+
const CodeJudgeEditText({
30+
super.key,
31+
required this.hint,
32+
this.multiline = true,
33+
this.suggestions = false,
34+
this.autocorrect = false,
35+
this.autofocus = true,
36+
this.textInputType = TextInputType.text,
37+
this.onInputDone,
38+
this.text,
39+
});
40+
41+
@override
42+
State<CodeJudgeEditText> createState() => _CodeJudgeEditTextState();
43+
}
44+
45+
class _CodeJudgeEditTextState extends State<CodeJudgeEditText> {
46+
late TextEditingController controller;
47+
late FocusNode focusNode;
48+
late String lastValue;
49+
50+
@override
51+
void initState() {
52+
super.initState();
53+
// Apply the controller
54+
controller = TextEditingController(text: widget.text);
55+
// Cursor at the end
56+
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
57+
58+
// Apply the FocusNode
59+
focusNode = FocusNode();
60+
61+
lastValue = controller.text.trim();
62+
}
63+
64+
@override
65+
Widget build(BuildContext context) {
66+
final int? maxLines = widget.multiline ? null : 1;
67+
68+
return TextField(
69+
controller: controller,
70+
autocorrect: widget.autocorrect,
71+
enableSuggestions: widget.suggestions,
72+
autofocus: widget.autofocus,
73+
maxLines: maxLines,
74+
textInputAction: widget.multiline ? TextInputAction.newline : TextInputAction.done,
75+
decoration: InputDecoration(
76+
hintText: widget.hint,
77+
filled: true,
78+
fillColor: Theme.of(context).colorScheme.surface,
79+
contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
80+
enabledBorder: OutlineInputBorder(
81+
borderRadius: BorderRadius.circular(8),
82+
borderSide: BorderSide(color: Theme.of(context).colorScheme.outline, width: 1),
83+
),
84+
focusedBorder: OutlineInputBorder(
85+
borderRadius: BorderRadius.circular(8),
86+
borderSide: BorderSide(color: Theme.of(context).colorScheme.primary, width: 2),
87+
),
88+
hintStyle: TextStyle(color: Theme.of(context).hintColor),
89+
),
90+
// Pefrom something everytime something changed
91+
onChanged: (value) {
92+
if (value != lastValue) {
93+
lastValue = value;
94+
widget.onInputDone?.call(value);
95+
}
96+
},
97+
);
98+
}
99+
100+
@override
101+
void didUpdateWidget(covariant CodeJudgeEditText oldWidget) {
102+
super.didUpdateWidget(oldWidget);
103+
104+
// Update the displayed text
105+
if (oldWidget.text != widget.text) {
106+
controller.text = widget.text ?? "";
107+
controller.selection = TextSelection.fromPosition(
108+
TextPosition(offset: controller.text.length),
109+
);
110+
}
111+
}
112+
113+
@override
114+
void dispose() {
115+
// Close everything
116+
focusNode.dispose();
117+
controller.dispose();
118+
super.dispose();
119+
}
120+
}

0 commit comments

Comments
 (0)