Membuat Aplikasi Android Sistem Informasi DesaKu - Part 18
Aplikasi Android Sistem Informasi Desaku ini merupakan Tutorial Part 18, jadi jika anda belum mengikuti [/membuat-aplikasi-android-sistem-informasi-desaku-part-16/]Tutorial Part 17 [/membuat-aplikasi-android-sistem-informasi-desaku-part-17/…
Aplikasi Android Sistem Informasi Desaku ini merupakan Tutorial Part 18, jadi jika anda belum mengikutiTutorial Part 17 diharapkan anda untuk mengikuti Tutorial Part 17 dahulu untuk memudahkan anda dalam memahami Tutorial Part 18 ini.
Pada Tutorial Part 17 sebelumnya kita membuat Folder Page dan juga menambahkan File Component disertai dengan penambahan code kemudian kita juga telah melakukan testing langsung melihat hasil dari perubahan code ke aplikasi android dengan menjalankan server debug. Pada Tutorial Part 18 ini kita akan melakukan perubahan code pada file Admin_Artikel_DesaKu.js
Baiklah sekarang buka folder project yaitu DesaKu dengan menggunakan Visual Studio Code

Project DesaKu
Sekarang buka file Admin_Artikel_DesaKu.js yang ada di folder src/screen/page .

Admin Artikel DesaKu
Kemudian sekarang lakukan perubahan code pada code import component dari react-native
- Awal code seperti ini
import {
View,
Text,
} from 'react-native'Perubahan Code seperti ini
import {
View,
Text,
StyleSheet,
Image,
StatusBar,
YellowBox,
TouchableOpacity,
FlatList,
ActivityIndicator,
RefreshControl,
Linking
} from 'react-native'Perubahan Code

Perubahan Code Import Component
Setelah itu lakukan penambahan code pada code constructor seperti berikut
constructor(props) {
super(props);
this.state = {
data:[],
isLoding: true,
refreshing: false
}
}Perubahan Code Consttructor

Perubahan Code Consttructor
Kemudian kita akan membuat sebuah function, function adalah digunakan untuk membungkus program menjadi bagian-bagian kecil. Buat dan letakan function setelah code constructor.
Admin_List_Artikel_DesaKu = () =>{
return fetch('https://sisteminformasidesaku.000webhostapp.com/api/Artikel_DesaKu/list_artikel_desaku.php')
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson)
this.setState({
isLoding:false,
data: responseJson
})
})
}Membuat Function

Membuat Function
Kemudian tambahkan code componentDidMount agar function nya dijalan otomatis ketika aplikasi dijalankan pada saat awal buka aplikasinya dan letakan code ini setelah code Function.
componentDidMount(){
this.Admin_List_Artikel_DesaKu()
}componentDidMount

componentDidMount
Setelah membuat sebuah fucntion componentDidMount seperti berikut codenya
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}FlatListItemSeparator

FlatListItemSeparator
Setelah membuat sebuah fucntion _onRefresh seperti berikut codenya.
_onRefresh(){
this.setState({refreshing: true}) ;
this.Admin_List_Artikel_DesaKu().then(() => {
this.setState({
refreshing: false
})
})
}Function _onRefresh

Function _onRefresh
Setelah membuat sebuah fucntion ListEmptyView seperti berikut codenya.
ListEmptyView = (isLoading = this.state.isLoading) => {
if (isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}else{
return (
<View>
<Text style={{textAlign: 'center'}}> Tidak Ada Data.</Text>
</View>
);
}
}Function ListEmptyView

Function ListEmptyView
Setelah membuat sebuah fucntion renderItems seperti berikut codenya.
renderItems = ({ item }) => {
const { id, title_artikel_desaku, tanggal_post_artikel_desaku, photo_artikel_desaku} = item
return (
<View style={styles.containerList}>
<View style={styles.conGambar}>
<Image source={{ uri: photo_artikel_desaku }} style={styles.gmbr} />
</View>
<View style={styles.note}>
<Text style={styles.Judul}>{title_artikel_desaku}</Text>
<Text style={styles.tgl}>{tanggal_post_artikel_desaku}</Text>
</View>
</View>
)
}Function renderItems

Function renderItems
Kemudian tambahkan code FlatList pada retrun, dan untuk posisinya anda bisa lihat digambar dibawah ini kemudian berikut code nya.
<View style={styles.maincontainer}>
<View style={styles.header}>
<Text style={styles.textHeader}>Artikel DesaKu</Text>
<Text style={styles.textHeader}>Logout</Text>
</View>
<FlatList
data={this.state.data}
ItemSeparatorComponent={this.FlatListItemSeparator}
keyExtractor={item => item.toString()}
renderItem={this.renderItems}
ListEmptyComponent={this.ListEmptyView}
refreshControl={
<RefreshControl refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
/>
</View> Code Di retrun

Code Di retrun
Kemudian tambahkan code styling berikut sebelum code export default
const styles = StyleSheet.create({
maincontainer:{
flex:1
},
containerList:{
margin:5,
backgroundColor:'#009688',
flexDirection:'row',
borderRadius: 15
},
gmbr:{
height: 100,
width: 100,
resizeMode:"center",
borderRadius: 20
},
conGambar:{
alignItems: 'center',
width: 120,
justifyContent:'center',
},
note:{
width: 220,
},
Judul:{
fontSize: 18,
fontWeight:'bold',
color:'#fff'
},
tgl:{
fontSize: 13,
color:'#fff'
},
Title:{
flexDirection:'row',
justifyContent:'space-between'
},
jdlTitle:{
fontSize:20,
fontWeight:'bold'
},
header:{
height: 40,
width: '100%',
backgroundColor: '#009688',
alignItems:'center',
justifyContent:'center',
flexDirection:'row',
justifyContent:'space-between',
},
textHeader:{
fontSize: 20,
color:'#fff',
fontWeight:'bold',
marginLeft: 10,
marginRight: 10
}
})Code Styling
Kemudian sekarang akan menambahkan Button Floating dengan cara menginstall library berikut ini. Saya harap ada bisa menginstall library atau jika bisa anda harus baca lagi Tutorial Part Sebelumnya.
sudo npm install --save react-native-action-button
sudo npm install --save react-native-vector-icons
sudo npm install --save react-native-modalbox@latestButton Floating
Jika proses install selesai sekarang tambahkan import component berikut ini kedalam file Admin_Artikel_DesaKu.js.
import ActionButton from 'react-native-action-button';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Modal from 'react-native-modalbox';Import Component

Import Component
Setelah itu tambahkan code berikut ini kedalam file android/app/build.gradle kemudian jangan lupa untuk melakukan react-native run-android .
project.ext.vectoricons = [
iconFontNames: [ 'MaterialIcons.ttf', 'EvilIcons.ttf' ] // Name of the font files you want to copy
]
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
React Native Vector

Tambahkan Code Berikut Ini
Kemudian tambahkan berikuti dibagian return dibawah Flatlist.
<ActionButton buttonColor="rgba(231,76,60,1)">
<ActionButton.Item buttonColor='#1abc9c' title="Add Artikel DesaKu" onPress={() => this.refs.modal7.open()}>
<Icon name="note-add" style={styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
ActionButton
Setelah itu tambahkan code ini dibagian styles
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white',
},styles

styles
Kemudian tambahkan code ini kedalam constructor
isOpen: false,
isDisabled: false,
swipeToClose: true,
sliderValue: 0.3Tambahan code di constructor

Tambahan code di constructor
Setalah itu tambahkan code berikut ini setelah constructor
onClose() {
console.log('Modal just closed');
}
onOpen() {
console.log('Modal just opened');
}
onClosingState(state) {
console.log('the open/close of the swipeToClose just changed');
}
renderList() {
var list = [];
for (var i=0;i<50;i++) {
list.push(<Text style={styles.text} key={i}>Elem {i}</Text>);
}
return list;
}Function

Function
Kemudian tambahkan code di antara render dan retrun
var BContent = (
<View style={[styles.btn, styles.btnModal]}>
<Text style= {{ color: '#fff'}} onPress={() => this.setState({isOpen: false})}>X</Text>
</View>
);BContent

BContent
Kemudian tambahkan code Modal berikut ini setelah ActionButon
<Modal style={[styles.modal, styles.modal3]} position={"center"} ref={"modal3"} isDisabled={this.state.isDisabled}>
<View>
<View style={styles.MainContainer}>
<Text style={{ fontSize: 25, textAlign: 'center', marginBottom: 7 }}> Tambah Artikel DesaKu </Text>
</View>
</View>
</Modal>Modal

MOdal
Setelah itu tambahkan code styling berikut ini di variabel styles
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white',
},
modal3: {
flex: 1,
backgroundColor: '#F0FFFF',
marginTop: 10,
marginBottom: 30,
marginLeft: 5,
marginRight: 10,
width: '90%',
borderRadius: 30
},
MainContainer: {
alignItems: 'center',
justifyContent: 'center'
},Styling

Styling
Kemudian kitakan menginstall 2 library yaitu rn-fetch-blob dan react-native-image-picker
sudo npm install --save rn-fetch-blob
sudo npm install --save react-native-image-pickerInstall Library
Setelah menginstall kedua library tersebut, langkah selanjutnya ada menjalankan perintah berikut ini.
react-native link
RNFB_ANDROID_PERMISSIONS=true react-native link rn-fetch-blob
Linking
Setelah itu lakukan install ulang aplikasi Debug dengan menjalankan perintah berikut ini.
react-native run-androidInstall Aplikasi Debug
Kemudian Import kedua library tersebut kedalam file Admin_Artikel_DesaKu.js
import ImagePicker from 'react-native-image-picker';
import RNFetchBlob from 'rn-fetch-blob';import library
Setelah itu tambahkan import component berikut ini.
TextInput,
PixelRatioImport Component
Dan tambahkan code pada constructor
ImageSource: null,
data: null,
title_artikel_desaku : ''
tanggal_post_artikel_desaku:''
penjelasan_artikel_desaku: ''Constructor

Perubahan Code
Kemudian tambahkan code berikuti ini setelah code constructor
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = { uri: response.uri };
this.setState({
ImageSource: source,
data: response.data
});
}
});
}Imagepicker

Imagepicker
Jangan lupa buat folder uploads dan tambakan code pada file tambah_artikel_desaku.php yang berada di folder Artikel_DesaKu di web https://files.000webhost.com/
<?php
//Define your host here.
$hostname = "localhost";
//Define your database User Name here.
$username = "id11934325_desaku";
//Define your database Password here.
$password = "Mikrotik@122";
//Define your Database Name here.
$dbname = "id11934325_desaku";
$conn = mysqli_connect($hostname, $username, $password, $dbname);
//mysql_select_db($dbname, $conn);
// Type your website name or domain name here.
$domain_name = "https://sisteminformasidesaku.000webhostapp.com/api/Artikel_DesaKu" ;
// Image uploading folder.
$penjelasan_artikel_desaku = "uploads/";
// Generating random image name each time so image name will not be same .
$penjelasan_artikel_desaku = $penjelasan_artikel_desaku . "/" .rand() . "_" . time() . ".jpeg";
// Receiving image tag sent from application.
$title_artikel_desaku = $_POST["title_artikel_desaku"];
$tanggal_post_artikel_desaku = $_POST["tanggal_post_artikel_desaku"];
$photo_artikel_desaku = $_POST["photo_artikel_desaku"];
$CheckSQL = "SELECT * FROM Artikel_DesaKu WHERE title_artikel_desaku='$title_artikel_desaku'";
// Executing SQL Query.
$check = mysqli_fetch_array(mysqli_query($conn,$CheckSQL));
// if( empty($title_artikel_desaku) || empty($tanggal_post_artikel_desaku) || empty($penjelasan_artikel_desaku)){
// $EmptyFormMessage = 'Pastikan Form Terisi...!';
// $EmptyFormJson = json_encode($EmptyFormMessage);
// echo $EmptyFormJson ;
// }
// else{
if(isset($check)){
$titleArtikelExistMSG = 'Data Sudah Ada !!!';
// Converting the message into JSON format.
$titleArtikelExistJson = json_encode($titleArtikelExistMSG);
// Echo the message.
echo $titleArtikelExistJson ;
}else{
// Receiving image sent from Application
if(move_uploaded_file($_FILES['image']['tmp_name'], $penjelasan_artikel_desaku)){
// Adding domain name with image random name.
$penjelasan_artikel_desaku = $domain_name . $penjelasan_artikel_desaku ;
$Sql_Query = "insert into Artikel_DesaKu ( title_artikel_desaku, tanggal_post_artikel_desaku, photo_artikel_desaku, penjelasan_artikel_desaku) VALUES('$title_artikel_desaku' , '$tanggal_post_artikel_desaku', '$photo_artikel_desaku', '$penjelasan_artikel_desaku')";
if(mysqli_query($conn,$Sql_Query)){
$MESSAGE = "Artikel Sukses Ditambahkan" ;
echo json_encode($MESSAGE);
}
else{
echo 'Please Try Again !!! ';
}
mysqli_close($conn);
}
}
// }
?>Kemudian tambahan code ini pada file Tambah_Artikel_DesaKu.js.
signOut =() =>{
AsyncStorage.removeItem('admin')
this.props.navigation.navigate('Auth')
}signOut

signOut
Tambahkan code TouchableOpacity pada TEXT logout
<TouchableOpacity onPress={() => this.signOut()}>
<Text style={styles.textHeader}>Logout</Text>
</TouchableOpacity>signOut

onPress SignOut
Berikut Code Lengkap File Admin_Artikel_DesaKu.js
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
Image,
StatusBar,
YellowBox,
TouchableOpacity,
FlatList,
ActivityIndicator,
RefreshControl,
Linking,
TextInput,
PixelRatio,
ScrollView,
AsyncStorage
} from 'react-native'
import ActionButton from 'react-native-action-button';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Modal from 'react-native-modalbox';
import ImagePicker from 'react-native-image-picker';
import RNFetchBlob from 'rn-fetch-blob';
class Admin_Artikel_DesaKu extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoding: true,
refreshing: false,
isOpen: false,
isDisabled: false,
swipeToClose: true,
sliderValue: 0.3,
ImageSource: null,
data: null,
title_artikel_desaku: '',
tanggal_post_artikel_desaku: '',
photo_artikel_desaku: '',
}
}
signOut =() =>{
AsyncStorage.removeItem('admin')
this.props.navigation.navigate('Auth')
}
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = { uri: response.uri };
this.setState({
ImageSource: source,
data: response.data
});
}
});
}
uploadImageToServer = () => {
RNFetchBlob.fetch('POST', 'https://sisteminformasidesaku.000webhostapp.com/api/Artikel_DesaKu/tambah_artikel_desaku.php', {
Authorization: "Bearer access-token",
otherHeader: "foo",
'Content-Type': 'multipart/form-data',
}, [
{ name: 'image', filename: 'image.png', type: 'image/png', data: this.state.data },
{ name: 'title_artikel_desaku', data: this.state.title_artikel_desaku },
{ name: 'tanggal_post_artikel_desaku', data: this.state.tanggal_post_artikel_desaku },
{ name: 'photo_artikel_desaku', data: this.state.photo_artikel_desaku },
]).then((resp) => {
var tempMSG = resp.data;
tempMSG = tempMSG.replace(/^"|"$/g, '');
alert(tempMSG);
}).catch((error) => {
console.error(error)
})
}
onClose() {
console.log('Modal just closed');
}
onOpen() {
console.log('Modal just opened');
}
onClosingState(state) {
console.log('the open/close of the swipeToClose just changed');
}
renderList() {
var list = [];
for (var i = 0; i < 50; i++) {
list.push(<Text style={styles.text} key={i}>Elem {i}</Text>);
}
return list;
}
Admin_List_Artikel_DesaKu = () => {
return fetch('https://sisteminformasidesaku.000webhostapp.com/api/Artikel_DesaKu/list_artikel_desaku.php')
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson)
this.setState({
isLoding: false,
data: responseJson
})
})
}
componentDidMount() {
this.Admin_List_Artikel_DesaKu()
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
_onRefresh() {
this.setState({ refreshing: true });
this.Admin_List_Artikel_DesaKu().then(() => {
this.setState({
refreshing: false
})
})
}
ListEmptyView = (isLoading = this.state.isLoading) => {
if (isLoading) {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<ActivityIndicator />
</View>
);
} else {
return (
<View>
<Text style={{ textAlign: 'center' }}> Tidak Ada Data.</Text>
</View>
);
}
}
renderItems = ({ item }) => {
const { id, title_artikel_desaku, tanggal_post_artikel_desaku, photo_artikel_desaku } = item
return (
<View style={styles.containerList}>
<View style={styles.conGambar}>
<Image source={{ uri: photo_artikel_desaku }} style={styles.gmbr} />
</View>
<View style={styles.note}>
<Text style={styles.Judul}>{title_artikel_desaku}</Text>
<Text style={styles.tgl}>{tanggal_post_artikel_desaku}</Text>
</View>
</View>
)
}
render() {
YellowBox.ignoreWarnings(['RNFetchBlob']);
var BContent = (
<View style={[styles.btn, styles.btnModal]}>
<Text style={{ color: '#fff' }} onPress={() => this.setState({ isOpen: false })}>X</Text>
</View>
);
return (
<View style={styles.maincontainer}>
<View style={styles.header}>
<Text style={styles.textHeader}>Artikel DesaKu</Text>
<TouchableOpacity onPress={() => this.signOut()}>
<Text style={styles.textHeader}>Logout</Text>
</TouchableOpacity>
</View>
<FlatList
data={this.state.data}
ItemSeparatorComponent={this.FlatListItemSeparator}
keyExtractor={item => item.toString()}
renderItem={this.renderItems}
ListEmptyComponent={this.ListEmptyView}
refreshControl={
<RefreshControl refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
/>
<ActionButton buttonColor="rgba(231,76,60,1)">
<ActionButton.Item buttonColor='#1abc9c' title="Add Artikel DesaKu" onPress={() => this.refs.modal3.open()}>
<Icon name="note-add" style={styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
<Modal style={[styles.modal, styles.modal3]} position={"center"} ref={"modal3"} isDisabled={this.state.isDisabled}>
<View>
<ScrollView>
<View style={styles.container}>
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={styles.ImageContainer}>
{this.state.ImageSource === null ? <Text>Select a Photo</Text> :
<Image style={styles.ImageContainer} source={this.state.ImageSource} />
}
</View>
</TouchableOpacity>
<TextInput
placeholder="Masukan Judul Artikel "
onChangeText={data => this.setState({ title_artikel_desaku: data })}
underlineColorAndroid='transparent'
style={styles.TextInputStyle}
/>
<TextInput
placeholder="Masukan Tgl Postingan "
onChangeText={data => this.setState({ tanggal_post_artikel_desaku: data })}
underlineColorAndroid='transparent'
style={styles.TextInputStyle}
/>
<TextInput
placeholder="Masukan Lokasi Posting Artikel "
onChangeText={data => this.setState({ photo_artikel_desaku: data })}
underlineColorAndroid='transparent'
style={styles.TextInputStyle}
/>
<TouchableOpacity onPress={this.uploadImageToServer} activeOpacity={0.6} style={styles.button} >
<Text style={styles.TextStyle}> Upload Now </Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
maincontainer: {
flex: 1
},
containerList: {
margin: 5,
backgroundColor: '#009688',
flexDirection: 'row',
borderRadius: 15
},
gmbr: {
height: 100,
width: 100,
resizeMode: "center",
borderRadius: 20
},
conGambar: {
alignItems: 'center',
width: 120,
justifyContent: 'center',
},
note: {
width: 220,
},
Judul: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff'
},
tgl: {
fontSize: 13,
color: '#fff'
},
Title: {
flexDirection: 'row',
justifyContent: 'space-between'
},
jdlTitle: {
fontSize: 20,
fontWeight: 'bold'
},
header: {
height: 40,
width: '100%',
backgroundColor: '#009688',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
},
textHeader: {
fontSize: 20,
color: '#fff',
fontWeight: 'bold',
marginLeft: 10,
marginRight: 10
},
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white',
},
modal3: {
flex: 1,
backgroundColor: '#F0FFFF',
marginTop: 10,
marginBottom: 30,
marginLeft: 5,
marginRight: 10,
width: '90%',
borderRadius: 30
},
MainContainer: {
alignItems: 'center',
justifyContent: 'center'
},
container: {
flex: 1,
alignItems: 'center',
paddingTop: 20
},
ImageContainer: {
borderRadius: 10,
width: 250,
height: 250,
borderColor: '#9B9B9B',
borderWidth: 1 / PixelRatio.get(),
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#CDDC39',
},
TextInputStyle: {
textAlign: 'center',
height: 40,
width: '80%',
borderRadius: 10,
borderWidth: 1,
borderColor: '#028b53',
marginTop: 20
},
TextInputStyleDetail: {
textAlign: 'center',
height: 50,
width: '80%',
borderRadius: 10,
borderWidth: 1,
borderColor: '#028b53',
marginTop: 20,
flexWrap:'wrap'
},
button: {
width: '80%',
backgroundColor: '#00BCD4',
borderRadius: 7,
marginTop: 20
},
TextStyle: {
color: '#fff',
textAlign: 'center',
padding: 10
}
})
export default Admin_Artikel_DesaKu;Code Versi Lengkap
Berikut tampilan pada aplikasi nya

Artikel DesaKu

Menu Tambah Artikel

Modal Tambah Artikel DesaKu
Demikian Tutorial Part 18 ini kita akan lanjutkan pada Tutorial Part 19
Catatan: tulisan ini dipindahkan dari cloudborneo.com, terbit pertama 18 Desember 2019.