@@ -2,6 +2,8 @@ import React from 'react';
2
2
import {
3
3
View ,
4
4
StyleSheet ,
5
+ StyleProp ,
6
+ ViewStyle ,
5
7
Text ,
6
8
TouchableOpacity ,
7
9
Animated ,
@@ -10,21 +12,27 @@ import {
10
12
TextInputFocusEventData ,
11
13
TextInputProps ,
12
14
} from 'react-native' ;
13
- import Icon from '../Icon' ;
14
- import { ButtonProps } from '../Button' ;
15
+ import Icon , { IconsProps } from '../Icon' ;
16
+ import Button , { ButtonProps } from '../Button' ;
15
17
import RightButton from './RightButton' ;
16
18
17
19
export interface SearchInputBarProps extends TextInputProps {
18
- /** 点击清除按钮时触发事件 */
19
- onClear ?: Function ;
20
+ /** 容器样式 */
21
+ containerStyle ?: StyleProp < ViewStyle > ;
20
22
/** 右侧按钮 */
21
23
button ?: ButtonProps ;
22
24
/** 右侧按钮文案 */
23
25
actionName ?: string ;
24
- /** 右侧按钮宽度默认70 */
25
- buttonWidth ?: number ;
26
- /** 是否一直显示右侧按钮 */
27
- showActionButton ?: boolean ;
26
+ /** 是否一直显示右侧按钮 null = 永不显示 */
27
+ showActionButton ?: boolean | null ;
28
+ /** 搜索图标 */
29
+ searchIcon ?: IconsProps ;
30
+ /** 点击搜索图标时触发事件 */
31
+ onSearch ?: Function ;
32
+ /** 清除图标 */
33
+ closeIcon ?: IconsProps ;
34
+ /** 点击清除图标时触发事件 */
35
+ onClear ?: Function ;
28
36
}
29
37
30
38
interface SearchInputBarState {
@@ -35,12 +43,7 @@ interface SearchInputBarState {
35
43
}
36
44
37
45
export default class SearchInputBar extends React . Component < SearchInputBarProps , SearchInputBarState > {
38
- private inputRef = React . createRef < TextInput > ( ) ;
39
- private moveLeft : Animated . Value = new Animated . Value ( 0 ) ;
40
- private placeholderIcon = React . createRef < View > ( ) ;
41
- private placeholderAnimated : Animated . Value = new Animated . Value ( 1 ) ;
42
- private buttonAnimated : Animated . Value = new Animated . Value ( this . props . buttonWidth ?? 70 ) ;
43
- private buttonAnimatedWidth : Animated . Value = new Animated . Value ( 0 ) ;
46
+ public inputRef = React . createRef < TextInput > ( ) ;
44
47
constructor ( props : SearchInputBarProps ) {
45
48
super ( props ) ;
46
49
this . state = {
@@ -49,198 +52,91 @@ export default class SearchInputBar extends React.Component<SearchInputBarProps,
49
52
} ;
50
53
}
51
54
52
- changeIconBoxStyle = ( flag : boolean ) => {
53
- if ( '_value' in this . buttonAnimatedWidth ) {
54
- const _value = ( this . buttonAnimatedWidth as any ) . _value ;
55
- if ( _value && ! flag ) {
56
- return ;
57
- }
58
- }
59
- const { buttonWidth = 70 , showActionButton } = this . props ;
60
- Animated . timing ( this . placeholderAnimated , {
61
- toValue : flag ? 1 : 0 ,
62
- duration : 50 ,
63
- useNativeDriver : true ,
64
- } ) . start ( ) ;
65
-
66
- Animated . timing ( this . buttonAnimated , {
67
- toValue : flag ? buttonWidth : 0 ,
68
- duration : 150 ,
69
- useNativeDriver : true ,
70
- } ) . start ( ( ) => { } ) ;
71
- this . buttonAnimatedWidth . setValue ( flag ? 0 : buttonWidth ) ;
72
-
73
- this . placeholderIcon . current &&
74
- this . placeholderIcon . current . measure (
75
- ( _frameOffsetX , _frameOffsetY , _width , _height , pageOffsetX , pageOffsetY ) => {
76
- const num = showActionButton ? 0 : buttonWidth ;
77
- Animated . timing ( this . moveLeft , {
78
- toValue : flag ? 0 : - pageOffsetX + 20 + num / 2 + 10 ,
79
- duration : 300 ,
80
- useNativeDriver : true ,
81
- } ) . start ( ( { finished } ) => {
82
- flag || ( this . inputRef . current && this . inputRef . current . focus ( ) ) ;
83
- } ) ;
84
- } ,
85
- ) ;
86
- } ;
87
- onChangeText = ( value : string ) => {
88
- const { onChangeText = Function } = this . props ;
89
- onChangeText ( value ) ;
90
- if ( ! value && this . state . showIcon ) {
91
- this . setState ( { showIcon : false } ) ;
92
- return ;
55
+ needFocus = ( type : 'search' | 'close' | 'actived' ) => {
56
+ if ( type === 'close' ) {
57
+ this . props . onClear ?.( ) ;
58
+ } else if ( type === 'search' ) {
59
+ this . props . onSearch ?.( ) ;
93
60
}
94
- if ( value && ! this . state . showIcon ) {
95
- this . inputRef . current &&
96
- this . inputRef . current . measure ( ( _frameOffsetX , _frameOffsetY , _width ) => {
97
- this . setState ( { showIconLeft : _width - 40 , showIcon : true } ) ;
98
- } ) ;
99
- }
100
- } ;
101
- componentDidMount ( ) {
102
- const { value, buttonWidth = 70 , showActionButton } = this . props ;
103
- if ( value ) {
104
- Animated . timing ( this . placeholderAnimated , {
105
- toValue : 1 ,
106
- duration : 100 ,
107
- useNativeDriver : true ,
108
- } ) . start ( ( ) => {
109
- this . changeIconBoxStyle ( false ) ;
110
- this . inputRef . current &&
111
- this . inputRef . current . measure ( ( _frameOffsetX , _frameOffsetY , _width ) => {
112
- let num = showActionButton ? 0 : buttonWidth ;
113
- this . setState ( { showIconLeft : _width - 40 - num ! , showIcon : true } ) ;
114
- } ) ;
115
- } ) ;
61
+ if ( type === 'actived' ) {
62
+ this . setState ( { showIcon : true } ) ;
116
63
}
117
- }
118
-
119
- onClose = ( ) => {
120
- const { onClear } = this . props ;
121
- onClear ?.( ) ;
122
- this . setState ( { showIcon : false } ) ;
64
+ console . log ( 'object' , type ) ;
123
65
this . inputRef . current && this . inputRef . current . focus ( ) ;
124
66
} ;
125
67
render ( ) {
126
- const { showIcon, showIconLeft } = this . state ;
127
68
const {
128
69
value,
129
- onBlur,
130
- placeholder = '请输入' ,
131
- buttonWidth = 70 ,
132
- showActionButton = false ,
70
+ onChangeText,
71
+ showActionButton,
72
+ actionName = '搜索' ,
133
73
button,
134
- actionName,
74
+ style,
75
+ containerStyle,
76
+ searchIcon,
77
+ closeIcon,
135
78
...other
136
79
} = this . props ;
137
80
return (
138
- < View style = { styles . searchContainer } >
139
- < View style = { [ styles . centerBox , { justifyContent : 'space-between' , overflow : 'hidden' } ] } >
81
+ < View style = { [ styles . centerFlex ] } >
82
+ < View style = { StyleSheet . flatten ( [ styles . searchContainer , styles . centerFlex , containerStyle ] ) } >
83
+ < View >
84
+ < TouchableOpacity style = { { } } onPress = { ( ) => this . needFocus ( 'search' ) } >
85
+ < Icon name = "search" size = { 18 } color = "#999" height = { '100%' } { ...searchIcon } />
86
+ </ TouchableOpacity >
87
+ </ View >
140
88
< TextInput
141
89
{ ...other }
142
- ref = { this . inputRef }
143
- style = { [ styles . searchInput , { flex : 1 } ] }
144
- onChangeText = { this . onChangeText }
145
90
value = { value }
146
- onBlur = { ( event : NativeSyntheticEvent < TextInputFocusEventData > ) => {
147
- if ( ! value ) {
148
- this . changeIconBoxStyle ( true ) ;
91
+ onChangeText = { onChangeText }
92
+ ref = { this . inputRef }
93
+ style = { [ styles . textInput , style ] }
94
+ onFocus = { ( e : NativeSyntheticEvent < TextInputFocusEventData > ) => {
95
+ if ( showActionButton !== null ) {
96
+ this . setState ( { showIcon : true } ) ;
149
97
}
150
- onBlur ?. ( event ) ;
98
+ other ?. onFocus ?. ( e ) ;
151
99
} }
152
- />
153
- < Animated . View style = { showActionButton ? { } : { transform : [ { translateX : this . buttonAnimated } ] } } >
154
- < Animated . View style = { showActionButton ? { } : { width : this . buttonAnimatedWidth } } >
155
- < RightButton width = { buttonWidth } isShow actionName = { actionName } { ...button } />
156
- </ Animated . View >
157
- </ Animated . View >
158
- </ View >
159
-
160
- < View style = { [ styles . iconBox , { justifyContent : 'space-between' , overflow : 'hidden' } ] } >
161
- < TouchableOpacity
162
- activeOpacity = { 1 }
163
- style = { [ styles . centerBox , { flex : 1 } ] }
164
- onPress = { ( ) => {
165
- this . changeIconBoxStyle ( false ) ;
100
+ onBlur = { ( e : NativeSyntheticEvent < TextInputFocusEventData > ) => {
101
+ this . setState ( { showIcon : false } ) ;
102
+ other ?. onBlur ?.( e ) ;
166
103
} }
167
- >
168
- < Animated . View style = { [ { transform : [ { translateX : this . moveLeft } ] } ] } >
169
- < View style = { [ styles . centerBox ] } ref = { this . placeholderIcon } >
170
- < Icon name = "search" size = { 18 } color = "#999" />
171
- </ View >
172
- </ Animated . View >
173
- < Animated . View style = { [ { transform : [ { translateX : this . moveLeft } ] } ] } >
174
- < Animated . View style = { [ styles . centerBox , { opacity : this . placeholderAnimated } ] } >
175
- < Text style = { styles . placeholderStyle } > { placeholder } </ Text >
176
- </ Animated . View >
177
- </ Animated . View >
178
- </ TouchableOpacity >
179
-
180
- < Animated . View style = { showActionButton ? { } : { transform : [ { translateX : this . buttonAnimated } ] } } >
181
- < Animated . View style = { showActionButton ? { } : { width : this . buttonAnimatedWidth } } >
182
- < RightButton width = { buttonWidth } isShow actionName = { actionName } { ...button } />
183
- </ Animated . View >
184
- </ Animated . View >
104
+ />
105
+ { Boolean ( value ) && (
106
+ < TouchableOpacity style = { { } } onPress = { ( ) => this . needFocus ( 'close' ) } >
107
+ < Icon name = "close" size = { 18 } color = "#999" height = { '100%' } { ...closeIcon } />
108
+ </ TouchableOpacity >
109
+ ) }
185
110
</ View >
186
-
187
- { showIcon && (
188
- < TouchableOpacity
189
- activeOpacity = { 1 }
190
- style = { [ styles . closeStyle , styles . centerBox , { left : showIconLeft } ] }
191
- onPress = { this . onClose }
192
- >
193
- < Icon name = "close" size = { 18 } color = "#999" />
194
- </ TouchableOpacity >
111
+ { ( showActionButton || this . state . showIcon ) && (
112
+ < Button type = "primary" { ...button } >
113
+ { actionName }
114
+ </ Button >
195
115
) }
196
116
</ View >
197
117
) ;
198
118
}
199
119
}
200
120
201
121
const styles = StyleSheet . create ( {
202
- searchContainer : {
203
- paddingHorizontal : 20 ,
204
- borderRadius : 5 ,
205
- height : 40 ,
206
- overflow : 'hidden' ,
207
- } ,
208
- iconBox : {
209
- height : 40 ,
210
- display : 'flex' ,
122
+ centerFlex : {
211
123
flexDirection : 'row' ,
212
- alignItems : 'center' ,
213
124
justifyContent : 'center' ,
214
- backgroundColor : 'transparent' ,
215
- position : 'relative' ,
216
- top : - 40 ,
217
- zIndex : 1 ,
125
+ alignContent : 'center' ,
218
126
} ,
219
- centerBox : {
220
- display : 'flex' ,
221
- flexDirection : 'row' ,
222
- alignItems : 'center' ,
223
- justifyContent : 'center' ,
224
- } ,
225
- placeholderStyle : {
226
- paddingLeft : 10 ,
227
- fontSize : 18 ,
228
- color : '#999' ,
229
- } ,
230
- searchInput : {
127
+ searchContainer : {
231
128
height : 40 ,
232
129
borderColor : 'gray' ,
233
130
borderWidth : 1 ,
234
131
borderRadius : 20 ,
235
- backgroundColor : '#f7f7f7' ,
236
- fontSize : 18 ,
237
- paddingHorizontal : 40 ,
132
+ flex : 1 ,
133
+ paddingHorizontal : 10 ,
134
+ marginRight : 10 ,
238
135
} ,
239
- closeStyle : {
240
- position : 'relative' ,
136
+ textInput : {
241
137
height : 40 ,
242
- width : 40 ,
243
- top : - 80 ,
244
- zIndex : 2 ,
138
+ flex : 1 ,
139
+ fontSize : 18 ,
140
+ paddingHorizontal : 8 ,
245
141
} ,
246
142
} ) ;
0 commit comments