@@ -2,6 +2,8 @@ import React from 'react';
22import {
33 View ,
44 StyleSheet ,
5+ StyleProp ,
6+ ViewStyle ,
57 Text ,
68 TouchableOpacity ,
79 Animated ,
@@ -10,21 +12,27 @@ import {
1012 TextInputFocusEventData ,
1113 TextInputProps ,
1214} 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' ;
1517import RightButton from './RightButton' ;
1618
1719export interface SearchInputBarProps extends TextInputProps {
18- /** 点击清除按钮时触发事件 */
19- onClear ?: Function ;
20+ /** 容器样式 */
21+ containerStyle ?: StyleProp < ViewStyle > ;
2022 /** 右侧按钮 */
2123 button ?: ButtonProps ;
2224 /** 右侧按钮文案 */
2325 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 ;
2836}
2937
3038interface SearchInputBarState {
@@ -35,12 +43,7 @@ interface SearchInputBarState {
3543}
3644
3745export 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 > ( ) ;
4447 constructor ( props : SearchInputBarProps ) {
4548 super ( props ) ;
4649 this . state = {
@@ -49,198 +52,91 @@ export default class SearchInputBar extends React.Component<SearchInputBarProps,
4952 } ;
5053 }
5154
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 ?.( ) ;
9360 }
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 } ) ;
11663 }
117- }
118-
119- onClose = ( ) => {
120- const { onClear } = this . props ;
121- onClear ?.( ) ;
122- this . setState ( { showIcon : false } ) ;
64+ console . log ( 'object' , type ) ;
12365 this . inputRef . current && this . inputRef . current . focus ( ) ;
12466 } ;
12567 render ( ) {
126- const { showIcon, showIconLeft } = this . state ;
12768 const {
12869 value,
129- onBlur,
130- placeholder = '请输入' ,
131- buttonWidth = 70 ,
132- showActionButton = false ,
70+ onChangeText,
71+ showActionButton,
72+ actionName = '搜索' ,
13373 button,
134- actionName,
74+ style,
75+ containerStyle,
76+ searchIcon,
77+ closeIcon,
13578 ...other
13679 } = this . props ;
13780 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 >
14088 < TextInput
14189 { ...other }
142- ref = { this . inputRef }
143- style = { [ styles . searchInput , { flex : 1 } ] }
144- onChangeText = { this . onChangeText }
14590 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 } ) ;
14997 }
150- onBlur ?. ( event ) ;
98+ other ?. onFocus ?. ( e ) ;
15199 } }
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 ) ;
166103 } }
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+ ) }
185110 </ 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 >
195115 ) }
196116 </ View >
197117 ) ;
198118 }
199119}
200120
201121const 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 : {
211123 flexDirection : 'row' ,
212- alignItems : 'center' ,
213124 justifyContent : 'center' ,
214- backgroundColor : 'transparent' ,
215- position : 'relative' ,
216- top : - 40 ,
217- zIndex : 1 ,
125+ alignContent : 'center' ,
218126 } ,
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 : {
231128 height : 40 ,
232129 borderColor : 'gray' ,
233130 borderWidth : 1 ,
234131 borderRadius : 20 ,
235- backgroundColor : '#f7f7f7' ,
236- fontSize : 18 ,
237- paddingHorizontal : 40 ,
132+ flex : 1 ,
133+ paddingHorizontal : 10 ,
134+ marginRight : 10 ,
238135 } ,
239- closeStyle : {
240- position : 'relative' ,
136+ textInput : {
241137 height : 40 ,
242- width : 40 ,
243- top : - 80 ,
244- zIndex : 2 ,
138+ flex : 1 ,
139+ fontSize : 18 ,
140+ paddingHorizontal : 8 ,
245141 } ,
246142} ) ;
0 commit comments