GitHub連結: https://github.com/l-urence/react-native-autocomplete-input
bouchertommy的中文參考:http://hant.helplib.com/GitHub/article_136892
以下針對Gitgub上example/Example.ios.js這個範例做個簡單的筆記:
1.Constructor 建構式:設定物件內的屬性(State)初始值
query: 紀錄輸入框所記錄的文字
films: 紀錄所有提示訊息
constructor(props) {
super(props);
this.state = {
films: [],
query: ''
};
}
2.componentDidMount: 生命週期,物件mount後執行componentDidMount() {
fetch(`${API}/films/`).then(res => res.json()).then((json) => {
const { results: films } = json;
this.setState({ films });
});
}
以fetch方法取得json格式的資料,從URL(https://swapi.co/api/films/)來看,可以看到會取得的內容如下,且將result內更新到State屬性的films中。3.findFilm: 根據目前輸入模糊查詢films內符合的並回傳。
findFilm(query) {
if (query === '') {
return [];
}
const { films } = this.state;
const regex = new RegExp(`${query.trim()}`, 'i');
return films.filter(film => film.title.search(regex) >= 0);
}
4.remderFilm: 選擇提示後回傳詳細內容。static renderFilm(film) {
const { title, director, opening_crawl, episode_id } = film;
const roman = episode_id < ROMAN.length ? ROMAN[episode_id] : episode_id;
return (
<View>
<Text style={styles.titleText}>{roman}. {title}</Text>
<Text style={styles.directorText}>({director})</Text>
<Text style={styles.openingText}>{opening_crawl}</Text>
</View>
);
}
const {title, director, opening_crawl, episode_id} = film;此行是將fims內的各個key取出Value。
5.
render() {
const { query } = this.state;
const films = this.findFilm(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return (
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
containerStyle={styles.autocompleteContainer}
data={films.length === 1 && comp(query, films[0].title) ? [] : films}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
placeholder="Enter Star Wars film title"
renderItem={({ title, release_date }) => (
<TouchableOpacity onPress={() => this.setState({ query: title })}>
<Text style={styles.itemText}>
{title} ({release_date.split('-')[0]})
</Text>
</TouchableOpacity>
)}
/>
<View style={styles.descriptionContainer}>
{films.length > 0 ? (
AutocompleteExample.renderFilm(films[0])
) : (
<Text style={styles.infoText}>
Enter Title of a Star Wars movie
</Text>
)}
</View>
</View>
);
}
第9行autoCapitalize及autoCorrect屬性(props)為關閉自動轉大寫及自動校正功能。第12行的data屬性為提示列表的內容,當提示篩選後(films)數量為1且與TextInput內容相同時設為空([])。
第13行的defaultValue屬性為TextInput內顯示的文字內容,每次State改變時呼叫render將取得query的值並設定到此屬性中。
方便自己包裝將此範例簡單改寫成以下,並帶入props的方法:
class AutocompleteExample extends Component {
static propTypes = {
films: PropTypes.array,
};
static defaultProps = {
films: [],
};
constructor(props) {
super(props);
this.state = {
text: ''
};
}
findFilm(text) {
{/*從輸入找出陣列符合*/}
if (text === '') {
return [];
}
const { films } = this.props;
const regex = new RegExp(`${text.trim()}`, 'i');
return films.filter(film => film.title.search(regex) >= 0);
}
render() {
const { text } = this.state;
const films = this.findFilm(text);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return (
<View >
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
containerStyle={styles.autocompleteContainer}
inputContainerStyle={{minWidth:115,maxWidth:200}}
data={films.length === 1 && comp(text, films[0].title) ? [] : films}
defaultValue={text}
onChangeText={text => this.setState({ text: text })}
placeholder="Enter Star Wars film title"
renderItem={
({title}) => (
<TouchableOpacity onPress={() => this.setState({ text: title })}>
{/*autocomplete 內容*/}
<Text style={styles.itemText}>
{title}
</Text>
</TouchableOpacity>
)
}
/>
</View>
);
}
}
接著呼叫改寫好的AutocompleteExample使用,例如:
export default class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<AutocompleteExample
films= {
[
{title:'001'},
{title:'002'},
{title:'003'},
{title:'004'},
{title:'005'},
{title:'006'},
{title:'007'},
{title:'008'},
{title:'009'},
{title:'010'},
{title:'011'},
{title:'012'},
{title:'013'},
{title:'014'},
]
}
/>
</View>
);
}
}
不過範例改寫完使用後,目前有發現兩個尚未解決Issue:
Issue1.提示訊息框並沒有ScrollView的功能
Issue2.提示訊息框呈現半透明,且如果UI有重疊的話會干擾點擊

沒有留言:
張貼留言