0
0
0
share
#Android#java#api#RecyclerView
0 Komentar
Cara Membuat Timeline Layout di Android
Pengantar
Timeline Layout bentuknya itu bisa berbagai macam dan semuanya itu tergantung dari datanya. Contoh seperti pada gambar diatas itu merupakan data yang menampilkan rute penerbangan. "Terus kapan timeline layout itu dipakai?" Kalau menurut penulis, sepertinya timeline layout cocok untuk menampilkan data yang berhubungan dengan data waktu, lokasi, dan lainnya seperti, menampilkan jam tayang jadwal bioskop, rute penerbangan pesawat, rute keberangkatan kereta api, jadwal dan rute keberangkatan bus, dan lain-lainnya. Oya, sebelum kita masuk ke projeknya mari kita analisa terlebih dahulu gambar diatas, kira-kira menurut para pembaca komponen(widget) apa aja yang ada pada gambar? Kalau menurut penulis, kira-kira seperti inilah hasil analisanya.
- Ada menggunakan TabLayout
- Ada beberapa TextView dengan size yang berbeda-beda dan ImageView
- Kemudian, yang bulat kecil di garis vertical itu sepertinya widget View yang diberi background custom drawable dengan solid darker gray
- Selanjutnya, untuk kotak yang garis putus-putus itu sepertinya hampir sama penggunaannya seperti poin nomor 3 hanya saja ini menggunakan TextView yang menggunakan background custom drawable dengan atribut dashGap dan corners radius
- Selanjutnya, ada apa lagi ya??? Oya, ada satu komponen penting pada gambar diatas yaitu, RecyclerView sebagai container.
Persiapan
Sebelum kita masuk, ke pembuatan projeknya ada beberapa hal yang perlu Anda persiapkan pada tutorial ini yaitu sebagai berikut.
- Pastikan Anda sudah memasang aplikasi Android Studio versi latest-nya di website canary android studio
- Pastikan juga Anda dalam kondisi terhubung ke internet karena, ada beberapa library dependency yang akan digunakan dalam pembuatan projek.
Pembuatan Projek
Pada tutorial ini, kita akan membuat aplikasi jadwal kereta api dengan sumber API-nya dari http://ibacor.com/. Bagi para pembaca yang belum mempunyai API key-nya saya sarankan daftar sekarang juga di website tersebut karena, pada tutorial ini kita wajib menggunakan API key. Pada tutorial ini, ada beberapa library yang saya pakai yaitu:
- EventBus GreenRobot
Pada projek ini, EventBus saya pakai untuk komunikasi data antar class. Karena, pada tutorial ini kita ada mengirimkan data POJO jadi, penggunaan EventBus menurut penulis cukup memudahkan proses pengirimannya. - Retrofit2
Kalau yang ini penulis menggunakan Retrofit2 sebagai salah satu teknik komunikasi ke server API untuk mengambil datanya. Sebenarnya, selain Retrofit2 Anda juga bisa memakai Volley namun, saya lebih suka dengan Retrofit2.
Untuk langkah pertama, silakan Anda buat projek baru di Android Studio dengan nama Codepolitan-JadwalKeretaApi selanjutnya, setting file build.gradle(Module:app) dan tambahkan beberapa library dependency berikut kedalam projek.
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:retrofit-converters:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'org.greenrobot:eventbus:3.0.0'
compile 'com.android.support:design:25.1.0'
testCompile 'junit:junit:4.12'
}
Colors.xml
Buka file Colors.xml dan ubah dengan source code berikut.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#009688</color>
<color name="colorPrimaryDark">#00796B</color>
<color name="colorAccent">#FF4081</color>
</resources>
Pembuatan File POJO
Nah, untuk pembuatan file POJO-nya saya rasa nggak mungkin saya jelaskan semuanya disini. Anda bisa membuatnya sendiri dari website www.jsonschema2pojo.org/ dan Anda bisa menggunakan aplikasi Postman untuk menangkap format response-nya dari server.
Pembuatan File API Service
Dalam penggunaan Retrofit, kita memerlukan sebuah file interface baru dalam penggunaannya. Di kelas interface tersebut akan kita deklarasikan baseApiUrl, Api Key dan path endpoint yang akan kita pakai pada tutorial ini. Silakan Anda buat file interface baru dengan nama KeretaApiService.java dan isi dengan source code berikut.
package ysn.codepolitan_jadwalkeretaapi.api;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.DataJadwal;
import ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.DataStasiun;
/**
* Created by root on 15/02/17.
*/
public interface KeretaApiService {
public final String baseApiUrl = "http://ibacor.com/";
public final String apiKey = "<Your API Key>";
@GET("api/kereta-api")
Call<DataStasiun> getDataStasiun(@Query("k") String apiKey);
@GET("api/kereta-api")
Call<ResponseBody> getDataJadwal(
@Query("tanggal") String tanggal,
@Query("asal") String asal,
@Query("tujuan") String tujuan,
@Query("k") String apiKey
);
}
Pembuatan File Pendukung
Pada tutorial ini, ada 3 file pendukung yang akan kita pakai pada bagian drawable yaitu, background_button.xml, background_circle_berangkat.xml, dan background_circle_datang.xml. Dan berikut source code dari setiap file tersebut.
background_button.xml
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
>
<selector>
<item
android:state_pressed="true"
>
<shape
android:shape="rectangle"
>
<corners
android:radius="5dp"
/>
<solid
android:color="@android:color/darker_gray"
/>
</shape>
</item>
<item>
<shape
android:shape="rectangle"
>
<corners
android:radius="5dp"
/>
<solid
android:color="@android:color/transparent"
/>
</shape>
</item>
</selector>
</inset>
background_circle_berangkat.xml
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
>
<selector>
<item>
<shape
android:shape="oval"
>
<solid
android:color="@color/colorPrimary"
/>
</shape>
</item>
</selector>
</inset>
background_circle_datang.xml
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
>
<selector>
<item>
<shape
android:shape="oval"
>
<solid
android:color="@color/colorAccent"
/>
</shape>
</item>
</selector>
</inset>
Splash Screen
Splash screen kita gunakan di awal aplikasi karena, untuk menampilkan data jadwal kereta api kita membutuhkan data awal dari server. Silakan buka file activity_main.xml dan ubah menjadi source code berikut.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:background="@color/colorPrimary"
tools:context="ysn.codepolitan_jadwalkeretaapi.activity.MainActivity"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_app_name_activity_main"
android:text="Jadwal Kereta Api"
android:textSize="30sp"
android:textColor="@android:color/white"
android:layout_centerInParent="true"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress_bar_activity_main"
android:layout_centerInParent="true"
android:layout_below="@+id/text_view_app_name_activity_main"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:indeterminate="true"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_try_again_activity_main"
android:layout_below="@+id/text_view_app_name_activity_main"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:text="Try Again"
android:visibility="gone"
/>
</RelativeLayout>
Selanjutnya, ubah juga source code pada file MainActivity.java menjadi seperti berikut.
package ysn.codepolitan_jadwalkeretaapi.activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import ysn.codepolitan_jadwalkeretaapi.R;
import ysn.codepolitan_jadwalkeretaapi.api.KeretaApiService;
import ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.DataStasiun;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivityTAG";
private static String data;
private Retrofit retrofit;
private Button buttonTryAgain;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeRetrofit();
loadComponent();
loadData();
}
private void loadComponent() {
progressBar = (ProgressBar) findViewById(R.id.progress_bar_activity_main);
buttonTryAgain = (Button) findViewById(R.id.button_try_again_activity_main);
buttonTryAgain.setOnClickListener(this);
}
private void loadData() {
KeretaApiService keretaApiService = retrofit.create(KeretaApiService.class);
final Call<DataStasiun> resultCallDataStasiun = keretaApiService.getDataStasiun(keretaApiService.apiKey);
resultCallDataStasiun.enqueue(new Callback<DataStasiun>() {
@Override
public void onResponse(Call<DataStasiun> call, Response<DataStasiun> response) {
Intent intent = new Intent(MainActivity.this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
EventBus.getDefault().postSticky(response.body());
startActivity(intent);
}
@Override
public void onFailure(Call<DataStasiun> call, Throwable t) {
t.printStackTrace();
Toast.makeText(MainActivity.this, "Koneksi timeout", Toast.LENGTH_LONG)
.show();
progressBar.setVisibility(View.GONE);
buttonTryAgain.setVisibility(View.VISIBLE);
}
});
}
private void initializeRetrofit() {
retrofit = new Retrofit.Builder()
.baseUrl(KeretaApiService.baseApiUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
@Override
public void onClick(View view) {
if (view == buttonTryAgain) {
progressBar.setVisibility(View.VISIBLE);
buttonTryAgain.setVisibility(View.GONE);
loadData();
}
}
}
Penjelasan singkat untuk logic dari file diatas ialah bahwa ketika aplikasi pertama kali dibuka maka, aplikasi akan melakukan request ke server untuk mengambil data awal yang kita perlukan untuk mencari data jadwal kereta api. Pada source code diatas bisa Anda lihat bahwa apabila request-nya sukses maka, kita akan menuju ke HomeActivity dan mengirimkan data POJO-nya lewat EventBus.
Form Cari Jadwal Kereta Api
Selanjutnya, silakan Anda buat activity baru dengan nama HomeActivity. Dan isi source code berikut pada file layout-nya.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="ysn.codepolitan_jadwalkeretaapi.activity.HomeActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_activity_home"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cek Jadwal Kereta Api"
android:textColor="@android:color/white"
android:textSize="18sp" />
</android.support.v7.widget.Toolbar>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_text_kota_asal_activity_home"
android:hint="Kota Asal"
android:focusable="false"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_text_kota_tujuan_activity_home"
android:hint="Kota Tujuan"
android:focusable="false"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_text_tanggal_keberangkatan_activity_home"
android:focusable="false"
android:hint="Tanggal Keberangkatan"
/>
</android.support.design.widget.TextInputLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_cek_jadwal_activity_home"
android:text="Cek Jadwal"
android:textColor="@color/colorPrimary"
android:layout_centerHorizontal="true"
android:background="@drawable/background_button"
android:minWidth="0dp"
android:minHeight="0dp"
android:paddingTop="13dp"
android:paddingRight="13dp"
android:paddingBottom="13dp"
android:paddingLeft="13dp"
/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
Dan isi juga source code berikut pada file HomeActivity.java.
package ysn.codepolitan_jadwalkeretaapi.activity;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import ysn.codepolitan_jadwalkeretaapi.R;
import ysn.codepolitan_jadwalkeretaapi.api.KeretaApiService;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.DataJadwal;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Kereta;
import ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.DataStasiun;
import ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.Stasiun;
import ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.Tanggal;
public class HomeActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "HomeActivityTAG";
private DataStasiun dataStasiun;
private Retrofit retrofit;
private EditText editTextAsalKeberangkatan;
private EditText editTextTujuanKeberangkatan;
private EditText editTextTanggalKeberangkatan;
private Button buttonCekJadwalKeberangkatan;
private List<String> listNamaKotaStasiun;
private List<String> listValueNamaKotaStasiun;
private List<String> listNamaKotaBesar;
private String valueKotaAsal;
private String valueKotaTujuan;
private String valueTanggal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
EventBus.getDefault().register(this);
initializeRetrofit();
loadComponent();
loadData();
}
private void initializeRetrofit() {
retrofit = new Retrofit.Builder()
.baseUrl(KeretaApiService.baseApiUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private void loadComponent() {
editTextAsalKeberangkatan = (EditText) findViewById(R.id.edit_text_kota_asal_activity_home);
editTextTujuanKeberangkatan = (EditText) findViewById(R.id.edit_text_kota_tujuan_activity_home);
editTextTanggalKeberangkatan = (EditText) findViewById(R.id.edit_text_tanggal_keberangkatan_activity_home);
buttonCekJadwalKeberangkatan = (Button) findViewById(R.id.button_cek_jadwal_activity_home);
editTextAsalKeberangkatan.setOnClickListener(this);
editTextTujuanKeberangkatan.setOnClickListener(this);
editTextTanggalKeberangkatan.setOnClickListener(this);
buttonCekJadwalKeberangkatan.setOnClickListener(this);
}
private void loadData() {
// list kota asal
listNamaKotaStasiun = new ArrayList<>();
listValueNamaKotaStasiun = new ArrayList<>();
listNamaKotaBesar = new ArrayList<>();
List<Stasiun> listStasiun = dataStasiun.getData().getStasiun();
for (Stasiun stasiun : listStasiun) {
String kotaBesar = stasiun.getKota();
kotaBesar = String.valueOf(kotaBesar.charAt(0)).toUpperCase() + "" + kotaBesar.substring(1).toLowerCase();
java.util.List<ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.List> listNamaKotaDetail = stasiun.getList();
for (ysn.codepolitan_jadwalkeretaapi.model.data_stasiun.List dataDetail : listNamaKotaDetail) {
String namaKotaStasiun = dataDetail.getName();
String valueNamaKotaStasiun = dataDetail.getValue();
listNamaKotaStasiun.add(namaKotaStasiun);
listValueNamaKotaStasiun.add(valueNamaKotaStasiun);
listNamaKotaBesar.add(kotaBesar);
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
/*EventBus.getDefault().unregister(this);*/
}
@Subscribe(sticky = true)
public void onMessageEvent(DataStasiun dataStasiun) {
if (dataStasiun != null) {
this.dataStasiun = dataStasiun;
}
}
@Subscribe
public void onMessageEvent(Map<String, Object> mapDataKota) {
if (mapDataKota != null && mapDataKota.containsKey("isKotaAsal")) {
boolean isKotaAsal = (boolean) mapDataKota.get("isKotaAsal");
String kotaValue = (String) mapDataKota.get("valueKota");
String kotaName = (String) mapDataKota.get("kotaName");
if (isKotaAsal) {
valueKotaAsal = kotaValue;
editTextAsalKeberangkatan.setText(kotaName);
} else {
valueKotaTujuan = kotaValue;
editTextTujuanKeberangkatan.setText(kotaName);
}
}
}
@Override
public void onClick(View view) {
if (view == editTextAsalKeberangkatan) {
Map<String, List<String>> mapListDataKotaAsal = new HashMap<>();
mapListDataKotaAsal.put("namaKotaStasiun", listNamaKotaStasiun);
mapListDataKotaAsal.put("valueNamaKotaStasiun", listValueNamaKotaStasiun);
mapListDataKotaAsal.put("namaKotaBesar", listNamaKotaBesar);
EventBus.getDefault().postSticky(mapListDataKotaAsal);
Intent intent = new Intent(this, KotaAsalTujuanActivity.class);
intent.putExtra("isActivityKotaAsal", true);
startActivity(intent);
} else if (view == editTextTujuanKeberangkatan) {
Map<String, List<String>> mapListDataKotaTujuan = new HashMap<>();
mapListDataKotaTujuan.put("namaKotaStasiun", listNamaKotaStasiun);
mapListDataKotaTujuan.put("valueNamaKotaStasiun", listValueNamaKotaStasiun);
mapListDataKotaTujuan.put("namaKotaBesar", listNamaKotaBesar);
EventBus.getDefault().postSticky(mapListDataKotaTujuan);
Intent intent = new Intent(this, KotaAsalTujuanActivity.class);
intent.putExtra("isActivityKotaAsal", false);
startActivity(intent);
} else if (view == editTextTanggalKeberangkatan) {
Calendar calendar = Calendar.getInstance();
DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker datePicker, int year, int month, int dayOfMonth) {
Calendar calendarSet = new GregorianCalendar();
calendarSet.set(Calendar.YEAR, year);
calendarSet.set(Calendar.MONTH, month);
calendarSet.set(Calendar.DAY_OF_MONTH, dayOfMonth);
editTextTanggalKeberangkatan.setText(new SimpleDateFormat("EEEE, dd MMMM yyyy").format(calendarSet.getTime()));
String namaHari = editTextTanggalKeberangkatan.getText().toString().split(",")[0];
if (namaHari.equalsIgnoreCase("Sunday")) {
namaHari = "Minggu,";
} else if (namaHari.equalsIgnoreCase("Monday")) {
namaHari = "Senin,";
} else if (namaHari.equalsIgnoreCase("Tuesday")) {
namaHari = "Selasa,";
} else if (namaHari.equalsIgnoreCase("Wednesday")) {
namaHari = "Rabu,";
} else if (namaHari.equalsIgnoreCase("Thursday")) {
namaHari = "Kamis,";
} else if (namaHari.equalsIgnoreCase("Friday")) {
namaHari = "Jumat,";
} else if (namaHari.equalsIgnoreCase("Saturday")) {
namaHari = "Sabtu,";
}
String namaBulan = editTextTanggalKeberangkatan.getText().toString().split(" ")[2];
if (namaBulan.equalsIgnoreCase("January")) {
namaBulan = "Januari";
} else if (namaBulan.equalsIgnoreCase("February")) {
namaBulan = "Februari";
} else if (namaBulan.equalsIgnoreCase("March")) {
namaBulan = "Maret";
} else if (namaBulan.equalsIgnoreCase("April")) {
namaBulan = "April";
} else if (namaBulan.equalsIgnoreCase("May")) {
namaBulan = "Mei";
} else if (namaBulan.equalsIgnoreCase("June")) {
namaBulan = "Juni";
} else if (namaBulan.equalsIgnoreCase("July")) {
namaBulan = "Juli";
} else if (namaBulan.equalsIgnoreCase("August")) {
namaBulan = "Agustus";
} else if (namaBulan.equalsIgnoreCase("September")) {
namaBulan = "September";
} else if (namaBulan.equalsIgnoreCase("October")) {
namaBulan = "Oktober";
} else if (namaBulan.equalsIgnoreCase("November")) {
namaBulan = "November";
} else if (namaBulan.equalsIgnoreCase("December")) {
namaBulan = "Desember";
}
String[] splitDate = editTextTanggalKeberangkatan.getText().toString().split(" ");
String strDate = namaHari + " " + splitDate[1] + " " + namaBulan + " " + splitDate[3];
editTextTanggalKeberangkatan.setText(strDate);
List<Tanggal> listTanggal = dataStasiun.getData().getTanggal();
for (Tanggal tanggal : listTanggal) {
String nameTanggal = tanggal.getName();
if (editTextTanggalKeberangkatan.getText().toString().equalsIgnoreCase(nameTanggal)) {
valueTanggal = tanggal.getValue();
break;
}
}
valueTanggal = (valueTanggal.equals("-") || TextUtils.isEmpty(valueTanggal)) ? "-" : valueTanggal;
}
}, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
datePickerDialog.show();
} else if (view == buttonCekJadwalKeberangkatan) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Harap tunggu");
progressDialog.setIndeterminate(true);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.show();
KeretaApiService keretaApiService = retrofit.create(KeretaApiService.class);
Call<ResponseBody> resultGetResponseBody = keretaApiService.getDataJadwal(valueTanggal, valueKotaAsal, valueKotaTujuan, KeretaApiService.apiKey);
resultGetResponseBody.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
progressDialog.dismiss();
try {
String dataJadwaljson = response.body().string();
JSONObject jsonObjectDataJadwalJson = new JSONObject(dataJadwaljson);
String status = jsonObjectDataJadwalJson.getString("status");
if (status.equalsIgnoreCase("Success")) {
EventBus.getDefault().postSticky(jsonObjectDataJadwalJson);
Intent intent = new Intent(HomeActivity.this, JadwalKeretaApiActivity.class);
intent.putExtra("kotaAsal", editTextAsalKeberangkatan.getText().toString());
intent.putExtra("kotaTujuan", editTextTujuanKeberangkatan.getText().toString());
intent.putExtra("tanggalJadwal", editTextTanggalKeberangkatan.getText().toString());
startActivity(intent);
} else {
Toast.makeText(HomeActivity.this, "Data jadwal tidak tersedia", Toast.LENGTH_LONG)
.show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
progressDialog.dismiss();
t.printStackTrace();
Toast.makeText(HomeActivity.this, "Koneksi timeout. Silakan coba lagi", Toast.LENGTH_LONG)
.show();
}
});
}
}
}
Pada source code HomeActivity.java, jika Anda lihat bahwa untuk menginput kota asal dan kota tujuannya itu kita menggunakan activity lain dengan nama KotaAsalTujuanActivity. Sebenarnya ini sifatnya opsional bagi Anda karena, Anda bisa menggunakan teknik lain seperti menggunakan Spinner atau EditText untuk menginput nama kota asal dan tujuannya. Hanya saja pada tutorial ini saya lebih suka menggunakan EditText dengan focusable-nya di nonaktifkan dan diberi onClickListener sehingga, proses inputnya itu dilakukan di activity lain dan membuat proses inputan nama kota asal dan tujuannya itu tidak di input melainkan di pilih dengan style searching gitu. Dan untuk menginput tanggal jadwalnya kita menggunakan DatePickerDialog dengan simple logic didalamnya agar formatnya itu sama seperti data yang di server jadi, kita bisa melakukan pencocokan dengan data server untuk mengambil value-nya.
Form Pilih Kota Asal dan Kota Tujuan
Silakan buat satu file activity baru dengan nama KotaAsalTujuanActivity dan isi source code berikut pada file layout-nya.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_kota_asal_tujuan"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ysn.codepolitan_jadwalkeretaapi.activity.KotaAsalTujuanActivity"
>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar_activity_kota_asal_tujuan"
android:background="@color/colorPrimary"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetRight="0dp"
app:contentInsetEnd="0dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="16dp"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_batal_activity_kota_asal_tujuan"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="Batal"
android:textColor="@android:color/white"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:background="@drawable/background_button"
android:minWidth="0dp"
android:minHeight="0dp"
android:paddingTop="13dp"
android:paddingRight="10dp"
android:paddingBottom="13dp"
android:paddingLeft="10dp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_text_input_kota_asal_activity_kota_asal_tujuan"
android:hint="Masukkan nama kota"
android:textColor="@android:color/white"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/button_batal_activity_kota_asal_tujuan"
android:layout_toStartOf="@+id/button_batal_activity_kota_asal_tujuan"
android:background="@android:color/transparent"
/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view_activity_kota_asal_tujuan"
android:layout_below="@+id/toolbar_activity_kota_asal_tujuan"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
/>
</RelativeLayout>
Kemudian, buat 1 file adapter dengan nama AdapterKotaAsalTujuan.java dan isi dengan source code berikut.
package ysn.codepolitan_jadwalkeretaapi.activity.adapter;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.List;
import java.util.Map;
import ysn.codepolitan_jadwalkeretaapi.R;
/**
* Created by root on 15/02/17.
*/
public class AdapterKotaAsalTujuan extends RecyclerView.Adapter<AdapterKotaAsalTujuan.ItemKotaAsalTujuanViewHolder> {
private static final String TAG = "AdapterTAG";
List<String> listNamaKotaStasiun;
List<String> listValueNamaKotaStasiun;
List<String> listNamaKotaBesar;
OnItemClickListener onItemClickListener;
public AdapterKotaAsalTujuan(List<String> listNamaKotaStasiun,
List<String> listValueNamaKotaStasiun,
List<String> listNamaKotaBesar,
OnItemClickListener onItemClickListener) {
this.listNamaKotaStasiun = listNamaKotaStasiun;
this.listValueNamaKotaStasiun = listValueNamaKotaStasiun;
this.listNamaKotaBesar = listNamaKotaBesar;
this.onItemClickListener = onItemClickListener;
}
@Override
public ItemKotaAsalTujuanViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_kota_asal_tujuan, null);
return new ItemKotaAsalTujuanViewHolder(view);
}
@Override
public void onBindViewHolder(ItemKotaAsalTujuanViewHolder holder, int position) {
holder.textViewNamaKotaStasiun.setText(listNamaKotaStasiun.get(position));
holder.textViewNamaKotaBesar.setText(listNamaKotaBesar.get(position));
holder.onClick(listValueNamaKotaStasiun.get(position), listNamaKotaStasiun.get(position));
}
@Override
public int getItemCount() {
return listNamaKotaStasiun.size();
}
public void refreshData(Map<String, List<String>> mapListData) {
listNamaKotaStasiun = mapListData.get("namaKotaStasiun");
listValueNamaKotaStasiun = mapListData.get("valueNamaKotaStasiun");
listNamaKotaBesar = mapListData.get("namaKotaBesar");
}
public class ItemKotaAsalTujuanViewHolder extends RecyclerView.ViewHolder {
private RelativeLayout relativeLayoutItem;
private TextView textViewNamaKotaStasiun;
private TextView textViewNamaKotaBesar;
public ItemKotaAsalTujuanViewHolder(View itemView) {
super(itemView);
relativeLayoutItem = (RelativeLayout) itemView.findViewById(R.id.relative_layout_item_kota_asal_tujuan);
textViewNamaKotaStasiun = (TextView) itemView.findViewById(R.id.text_view_nama_kota_stasiun_item_kota_asal_tujuan);
textViewNamaKotaBesar = (TextView) itemView.findViewById(R.id.text_view_nama_kota_besar_item_kota_asal_tujuan);
}
public void onClick(final String value, final String kota) {
relativeLayoutItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onClick(value, kota);
}
});
}
}
public interface OnItemClickListener {
void onClick(String valueKota, String kotaName);
}
}
Dan selanjutnya, ubah juga source code pada file KotaAsalTujuanActivity.java menjadi seperti berikut.
package ysn.codepolitan_jadwalkeretaapi.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ysn.codepolitan_jadwalkeretaapi.R;
import ysn.codepolitan_jadwalkeretaapi.activity.adapter.AdapterKotaAsalTujuan;
public class KotaAsalTujuanActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "KotaAsalTAG";
private EditText editTextInputKotaAsal;
private Button buttonBatal;
private RecyclerView recyclerViewKotaAsal;
private AdapterKotaAsalTujuan adapterKotaAsalTujuan;
private List<String> listNamaKotaStasiun;
private List<String> listValueNamaKotaStasiun;
private List<String> listNamaKotaBesar;
private boolean isActivityKotaAsal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_kota_asal_tujuan);
EventBus.getDefault().register(this);
loadComponent();
loadData();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
private void loadComponent() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_activity_kota_asal_tujuan);
setSupportActionBar(toolbar);
editTextInputKotaAsal = (EditText) findViewById(R.id.edit_text_input_kota_asal_activity_kota_asal_tujuan);
buttonBatal = (Button) findViewById(R.id.button_batal_activity_kota_asal_tujuan);
recyclerViewKotaAsal = (RecyclerView) findViewById(R.id.recycler_view_activity_kota_asal_tujuan);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerViewKotaAsal.setLayoutManager(layoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
recyclerViewKotaAsal.addItemDecoration(dividerItemDecoration);
editTextInputKotaAsal.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String keywordInputNamaKota = editTextInputKotaAsal.getText().toString();
Map<String, List<String>> mapListData = new HashMap<String, List<String>>();
if (TextUtils.isEmpty(keywordInputNamaKota)) {
mapListData.put("namaKotaStasiun", listNamaKotaStasiun);
mapListData.put("valueNamaKotaStasiun", listValueNamaKotaStasiun);
mapListData.put("namaKotaBesar", listNamaKotaBesar);
adapterKotaAsalTujuan.refreshData(mapListData);
adapterKotaAsalTujuan.notifyDataSetChanged();
} else {
List<String> listNamaKotaStasiunKeyword = new ArrayList<String>();
List<String> listValueNamaKotaStasiunKeyword = new ArrayList<String>();
List<String> listNamaKotaBesarKeyword = new ArrayList<String>();
for(int a = 0; a < listNamaKotaStasiun.size(); a++) {
if (listNamaKotaStasiun.get(a).toLowerCase().contains(keywordInputNamaKota.toLowerCase())
|| listNamaKotaBesar.get(a).toLowerCase().contains(keywordInputNamaKota.toLowerCase())) {
listNamaKotaStasiunKeyword.add(listNamaKotaStasiun.get(a));
listValueNamaKotaStasiunKeyword.add(listValueNamaKotaStasiun.get(a));
listNamaKotaBesarKeyword.add(listNamaKotaBesar.get(a));
}
}
mapListData.put("namaKotaStasiun", listNamaKotaStasiunKeyword);
mapListData.put("valueNamaKotaStasiun", listValueNamaKotaStasiunKeyword);
mapListData.put("namaKotaBesar", listNamaKotaBesarKeyword);
adapterKotaAsalTujuan.refreshData(mapListData);
adapterKotaAsalTujuan.notifyDataSetChanged();
}
}
});
buttonBatal.setOnClickListener(this);
}
private void loadData() {
recyclerViewKotaAsal.setAdapter(adapterKotaAsalTujuan);
}
@Override
public void onClick(View view) {
if (view == buttonBatal) {
finish();
}
}
@Subscribe(sticky = true)
public void onMessageEvent(Map<String, List<String>> mapListData) {
listNamaKotaStasiun = mapListData.get("namaKotaStasiun");
listValueNamaKotaStasiun = mapListData.get("valueNamaKotaStasiun");
listNamaKotaBesar = mapListData.get("namaKotaBesar");
Bundle bundle = getIntent().getExtras();
isActivityKotaAsal = bundle.getBoolean("isActivityKotaAsal");
AdapterKotaAsalTujuan.OnItemClickListener onItemClickListener = new AdapterKotaAsalTujuan.OnItemClickListener() {
@Override
public void onClick(String valueKota, String kotaName) {
Map<String, Object> mapDataKota = new HashMap<>();
mapDataKota.put("valueKota", valueKota);
mapDataKota.put("kotaName", kotaName);
mapDataKota.put("isKotaAsal", isActivityKotaAsal);
EventBus.getDefault().post(mapDataKota);
finish();
}
};
adapterKotaAsalTujuan = new AdapterKotaAsalTujuan(listNamaKotaStasiun, listValueNamaKotaStasiun, listNamaKotaBesar, onItemClickListener);
}
}
Form Data Jadwal Kereta Api
Nah, fokusnya disini. Karena, timeline layout-nya itu ada di sini. Pada Form Jadwal Kereta Api ini kita menggunakan RecyclerView sebagai container-nya. Dan untuk item dari RecyclerView-nya kita membuat 3 jenis item yaitu, item bagian header, item bagian konten, dan item bagian footer. Sekarang, silakan Anda buat ketiga file item tersebut. Untuk item pertama, silakan Anda buat file layout baru dengan nama item_jadwal_kereta_api_header.xml dan isi dengan source code berikut.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
>
<View
android:layout_width="1dp"
android:layout_height="24dp"
android:background="@android:color/darker_gray"
android:layout_marginLeft="100dp"
android:layout_marginStart="100dp"
/>
</RelativeLayout>
Yap, dibagian headernya kita memang cuma buat garis vertikalnya doang. Hal ini sengaja penulis buat agar bagian kontennya itu tidak perlu diberi margin.
Untuk item kedua, silakan Anda buat file layout baru dengan nama item_jadwal_kereta_api.xml dan isi dengan source code berikut.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<View
android:layout_width="1dp"
android:layout_height="210dp"
android:background="@android:color/darker_gray"
android:layout_marginLeft="100dp"
android:layout_marginStart="100dp"
/>
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:id="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:background="@drawable/background_circle_berangkat"
android:layout_marginLeft="90dp"
android:layout_marginStart="90dp"
android:layout_marginTop="70dp"
/>
<TextView
android:layout_width="85dp"
android:layout_height="wrap_content"
android:id="@+id/text_view_jam_berangkat_item_jadwal_kereta_api"
android:layout_marginTop="67dp"
android:text="10:13"
android:gravity="center"
/>
<TextView
android:layout_width="85dp"
android:layout_height="wrap_content"
android:id="@+id/text_view_tanggal_berangkat_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_jam_berangkat_item_jadwal_kereta_api"
android:text="18 Feb 2017"
android:gravity="center"
android:layout_marginTop="5dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_nama_kereta_api_item_jadwal_kereta_api"
android:text="SRIBILAH UTAMA (U43)"
android:textSize="15sp"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_kelas_subkelas_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_nama_kereta_api_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="3dp"
android:text="Kelas Eksekutif - I"
android:textSize="13sp"
android:textColor="@android:color/darker_gray"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_harga_tiket_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_kelas_subkelas_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="3dp"
android:text="Rp 135.000"
android:textSize="13sp"
android:textColor="@android:color/darker_gray"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_kota_asal_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="70dp"
android:text="BATANGKUIS"
android:textSize="15sp"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/view_line_horizontal_atas_durasi_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_kota_asal_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_durasi_item_jadwal_kereta_api"
android:layout_below="@+id/view_line_horizontal_atas_durasi_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:text="Durasi 3j 36m"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/view_line_horizontal_bawah_durasi_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_durasi_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="8dp"
android:background="@android:color/darker_gray"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_kota_tujuan_item_jadwal_kereta_api"
android:layout_below="@+id/view_line_horizontal_bawah_durasi_item_jadwal_kereta_api"
android:layout_toRightOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginLeft="15dp"
android:layout_marginStart="15dp"
android:layout_toEndOf="@+id/view_circle_berangkat_item_jadwal_kereta_api"
android:layout_marginTop="16dp"
android:text="MEDAN"
android:textSize="15sp"
/>
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:id="@+id/view_circle_datang_item_jadwal_kereta_api"
android:background="@drawable/background_circle_datang"
android:layout_marginLeft="90dp"
android:layout_marginStart="90dp"
android:layout_below="@+id/view_line_horizontal_bawah_durasi_item_jadwal_kereta_api"
android:layout_marginTop="16dp"
/>
<TextView
android:layout_width="85dp"
android:layout_height="wrap_content"
android:id="@+id/text_view_jam_datang_item_jadwal_kereta_api"
android:text="13:49"
android:gravity="center"
android:layout_below="@+id/view_line_horizontal_bawah_durasi_item_jadwal_kereta_api"
android:layout_marginTop="13dp"
/>
<TextView
android:layout_width="85dp"
android:layout_height="wrap_content"
android:id="@+id/text_view_tanggal_datang_item_jadwal_kereta_api"
android:layout_below="@+id/text_view_jam_datang_item_jadwal_kereta_api"
android:layout_marginTop="5dp"
android:text="18 Feb 2017"
android:gravity="center"
/>
</RelativeLayout>
</RelativeLayout>
Dan untuk item yang terakhir, silakan Anda buat file layout baru dengan nama item_jadwal_kereta_api_footer.xml dan isi dengan source code berikut.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relative_line_vertical_item_jadwal_kereta_api_footer"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
>
<View
android:layout_width="1dp"
android:layout_height="24dp"
android:background="@android:color/darker_gray"
android:layout_marginLeft="100dp"
android:layout_marginStart="100dp"
/>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray"
android:layout_below="@+id/relative_line_vertical_item_jadwal_kereta_api_footer"
/>
</RelativeLayout>
Dibagian footernya pun kita juga membuat garis vertikalnya saja hampir sama seperti bagian headernya namun, ada garis horizontalnya juga.
Sekarang, sebelum masuk ke kode utamanya mari kita buat terlebih dahulu file adapternya dengan nama AdapterJadwalKeretaApi.java dan isi dengan source code berikut.
package ysn.codepolitan_jadwalkeretaapi.activity.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import ysn.codepolitan_jadwalkeretaapi.R;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Datum;
/**
* Created by root on 16/02/17.
*/
public class AdapterJadwalKeretaApi extends RecyclerView.Adapter<AdapterJadwalKeretaApi.ViewHolder> {
public static final int ITEM_HEADER = 1;
public static final int ITEM_CONTENT = 2;
public static final int ITEM_FOOTER = 3;
List<Datum> listDatum;
List<Integer> listViewType;
String kotaAsal;
String kotaTujuan;
public AdapterJadwalKeretaApi(List<Datum> listDatum,
List<Integer> listViewType,
String kotaAsal,
String kotaTujuan) {
this.listDatum = listDatum;
this.listViewType = listViewType;
this.kotaAsal = kotaAsal;
this.kotaTujuan = kotaTujuan;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == ITEM_HEADER) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_jadwal_kereta_api_header, null);
return new ItemJadwalKeretaApiHeaderViewHolder(view);
} else if (viewType == ITEM_CONTENT) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_jadwal_kereta_api, null);
return new ItemJadwalKeretaApiViewHolder(view);
} else if (viewType == ITEM_FOOTER) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_jadwal_kereta_api_footer, null);
return new ItemJadwalKeretaApiFooterViewHolder(view);
} else {
return null;
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
int viewType = listViewType.get(position);
if (viewType == ITEM_HEADER || viewType == ITEM_FOOTER) {
// nothing to do in here
} else if (viewType == ITEM_CONTENT) {
ItemJadwalKeretaApiViewHolder itemJadwalKeretaApiViewHolder = (ItemJadwalKeretaApiViewHolder) holder;
Datum datum = listDatum.get(position);
itemJadwalKeretaApiViewHolder.textViewNamaKeretaApi.setText(datum.getKereta().getName());
itemJadwalKeretaApiViewHolder.textViewKelasSubKelas.setText(datum.getKereta().getClass_() + " - " + datum.getHarga().getSubclass());
itemJadwalKeretaApiViewHolder.textViewHargaTiket.setText("Rp " + datum.getHarga().getRp());
itemJadwalKeretaApiViewHolder.textViewJamBerangkat.setText(datum.getBerangkat().getJam());
itemJadwalKeretaApiViewHolder.textViewTanggalBerangkat.setText(datum.getBerangkat().getTanggal());
itemJadwalKeretaApiViewHolder.textViewKotaAsal.setText(kotaAsal);
itemJadwalKeretaApiViewHolder.textViewDurasi.setText("Durasi " + datum.getDurasi());
itemJadwalKeretaApiViewHolder.textViewJamDatang.setText(datum.getDatang().getJam());
itemJadwalKeretaApiViewHolder.textViewTanggalDatang.setText(datum.getDatang().getTanggal());
itemJadwalKeretaApiViewHolder.textViewKotaTujuan.setText(kotaTujuan);
}
}
@Override
public int getItemCount() {
return listDatum.size();
}
@Override
public int getItemViewType(int position) {
return listViewType.get(position);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
public class ItemJadwalKeretaApiHeaderViewHolder extends ViewHolder {
public ItemJadwalKeretaApiHeaderViewHolder(View itemView) {
super(itemView);
}
}
public class ItemJadwalKeretaApiFooterViewHolder extends ViewHolder {
public ItemJadwalKeretaApiFooterViewHolder(View itemView) {
super(itemView);
}
}
public class ItemJadwalKeretaApiViewHolder extends ViewHolder {
private TextView textViewNamaKeretaApi;
private TextView textViewKelasSubKelas;
private TextView textViewHargaTiket;
private TextView textViewJamBerangkat;
private TextView textViewTanggalBerangkat;
private TextView textViewKotaAsal;
private TextView textViewDurasi;
private TextView textViewJamDatang;
private TextView textViewTanggalDatang;
private TextView textViewKotaTujuan;
public ItemJadwalKeretaApiViewHolder(View itemView) {
super(itemView);
textViewNamaKeretaApi = (TextView) itemView.findViewById(R.id.text_view_nama_kereta_api_item_jadwal_kereta_api);
textViewKelasSubKelas = (TextView) itemView.findViewById(R.id.text_view_kelas_subkelas_item_jadwal_kereta_api);
textViewHargaTiket = (TextView) itemView.findViewById(R.id.text_view_harga_tiket_item_jadwal_kereta_api);
textViewJamBerangkat = (TextView) itemView.findViewById(R.id.text_view_jam_berangkat_item_jadwal_kereta_api);
textViewTanggalBerangkat = (TextView) itemView.findViewById(R.id.text_view_tanggal_berangkat_item_jadwal_kereta_api);
textViewKotaAsal = (TextView) itemView.findViewById(R.id.text_view_kota_asal_item_jadwal_kereta_api);
textViewDurasi = (TextView) itemView.findViewById(R.id.text_view_durasi_item_jadwal_kereta_api);
textViewJamDatang = (TextView) itemView.findViewById(R.id.text_view_jam_datang_item_jadwal_kereta_api);
textViewTanggalDatang = (TextView) itemView.findViewById(R.id.text_view_tanggal_datang_item_jadwal_kereta_api);
textViewKotaTujuan = (TextView) itemView.findViewById(R.id.text_view_kota_tujuan_item_jadwal_kereta_api);
}
}
}
Jika, sebelumnya Anda sudah pernah membaca atau mengikuti tutorial saya sebelumnya pasti Anda tahu bahwa pada adapter ini kita menggunakan teknik multiple view type.
Dan selanjutnya, buat activity baru dengan nama JadwalKeretaApiActivity dan silakan Anda ubah isi file layout-nya menjadi seperti berikut.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ysn.codepolitan_jadwalkeretaapi.activity.JadwalKeretaApiActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Jadwal Kereta Api"
android:textColor="@android:color/white"
android:textSize="18sp" />
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:id="@+id/relative_layout_keterangan_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar_activity_jadwal_kereta_api"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<RelativeLayout
android:id="@+id/relative_layout_header_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/text_view_kota_asal_activity_jadwal_kereta_api"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginEnd="19dp"
android:layout_marginRight="19dp"
android:text="BATANGKUIS"
android:textSize="17sp" />
<TextView
android:id="@+id/text_view_kota_tujuan_activity_jadwal_kereta_api"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginLeft="19dp"
android:layout_marginStart="19dp"
android:text="MEDAN"
android:textSize="17sp" />
<View
android:id="@+id/view_line_horizontal_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/text_view_kota_asal_activity_jadwal_kereta_api"
android:layout_toLeftOf="@+id/text_view_kota_tujuan_activity_jadwal_kereta_api"
android:layout_toRightOf="@+id/text_view_kota_asal_activity_jadwal_kereta_api"
android:layout_toStartOf="@+id/text_view_kota_tujuan_activity_jadwal_kereta_api"
android:background="@android:color/darker_gray" />
<View
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/view_line_horizontal_activity_jadwal_kereta_api"
android:background="@drawable/background_circle_berangkat" />
<View
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/view_line_horizontal_activity_jadwal_kereta_api"
android:background="@drawable/background_circle_datang" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/relative_layout_header_activity_jadwal_kereta_api">
<TextView
android:id="@+id/text_view_kota_asal_placeholder_activity_jadwal_kereta_api"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginEnd="19dp"
android:layout_marginRight="19dp"
android:text="BATANGKUIS"
android:textSize="17sp"
android:visibility="invisible" />
<TextView
android:id="@+id/text_view_kota_tujuan_placeholder_activity_jadwal_kereta_api"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginLeft="19dp"
android:layout_marginStart="19dp"
android:text="MEDAN"
android:textSize="17sp"
android:visibility="invisible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view_tanggal_jadwal_activity_jadwal_kereta_api"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_toEndOf="@+id/text_view_kota_asal_placeholder_activity_jadwal_kereta_api"
android:layout_toLeftOf="@+id/text_view_kota_tujuan_placeholder_activity_jadwal_kereta_api"
android:layout_toRightOf="@+id/text_view_kota_asal_placeholder_activity_jadwal_kereta_api"
android:layout_toStartOf="@+id/text_view_kota_tujuan_placeholder_activity_jadwal_kereta_api"
android:gravity="center"
android:text="Rabu, 15 Februari 2017"
android:textColor="@android:color/darker_gray"
android:textSize="13sp" />
</RelativeLayout>
</RelativeLayout>
<View
android:id="@+id/view_line_horizontal_2_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/relative_layout_keterangan_activity_jadwal_kereta_api"
android:background="@android:color/darker_gray" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view_activity_jadwal_kereta_api"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/view_line_horizontal_2_activity_jadwal_kereta_api" />
</RelativeLayout>
Dan yang terakhir, silakan Anda ubah file JadwalKeretaApiActivity.java menjadi seperti berikut.
package ysn.codepolitan_jadwalkeretaapi.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.TextView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import ysn.codepolitan_jadwalkeretaapi.R;
import ysn.codepolitan_jadwalkeretaapi.activity.adapter.AdapterJadwalKeretaApi;
import ysn.codepolitan_jadwalkeretaapi.api.KeretaApiService;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Berangkat;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.DataJadwal;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Datang;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Datum;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Harga;
import ysn.codepolitan_jadwalkeretaapi.model.data_jadwal.Kereta;
public class JadwalKeretaApiActivity extends AppCompatActivity {
private Retrofit retrofit;
private DataJadwal dataJadwal;
private TextView textViewKotaAsal;
private TextView textViewKotaTujuan;
private TextView textViewTanggalJadwal;
private RecyclerView recyclerViewJadwal;
private List<Datum> listDatum;
private List<Integer> listViewType;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jadwal_kereta_api);
EventBus.getDefault().register(this);
initializeRetrofit();
loadComponent();
loadAdapter();
}
private void loadAdapter() {
AdapterJadwalKeretaApi adapterJadwalKeretaApi = new AdapterJadwalKeretaApi(listDatum, listViewType, textViewKotaAsal.getText().toString(), textViewKotaTujuan.getText().toString());
recyclerViewJadwal.setAdapter(adapterJadwalKeretaApi);
}
private void loadComponent() {
textViewKotaAsal = (TextView) findViewById(R.id.text_view_kota_asal_activity_jadwal_kereta_api);
textViewKotaTujuan = (TextView) findViewById(R.id.text_view_kota_tujuan_activity_jadwal_kereta_api);
textViewTanggalJadwal = (TextView) findViewById(R.id.text_view_tanggal_jadwal_activity_jadwal_kereta_api);
recyclerViewJadwal = (RecyclerView) findViewById(R.id.recycler_view_activity_jadwal_kereta_api);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerViewJadwal.setLayoutManager(layoutManager);
Bundle bundle = getIntent().getExtras();
textViewKotaAsal.setText(bundle.getString("kotaAsal"));
textViewKotaTujuan.setText(bundle.getString("kotaTujuan"));
textViewTanggalJadwal.setText(bundle.getString("tanggalJadwal"));
}
private void initializeRetrofit() {
retrofit = new Retrofit.Builder()
.baseUrl(KeretaApiService.baseApiUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
@Subscribe(sticky = true)
public void onMessageEvent(JSONObject jsonObjectDataJadwal) {
try {
// data
JSONArray jsonArrayData = jsonObjectDataJadwal.getJSONArray("data");
listDatum = new ArrayList<>();
listViewType = new ArrayList<>();
for(int a = 0; a < jsonArrayData.length(); a++) {
JSONObject jsonObjectItemData = jsonArrayData.getJSONObject(a);
Datum datum = new Datum();
// tiket
String tiket = jsonObjectItemData.getString("tiket");
if (!tiket.equalsIgnoreCase("Tersedia")) {
continue;
}
listViewType.add(AdapterJadwalKeretaApi.ITEM_HEADER);
listViewType.add(AdapterJadwalKeretaApi.ITEM_CONTENT);
listViewType.add(AdapterJadwalKeretaApi.ITEM_FOOTER);
// kereta
JSONObject jsonObjectKereta = jsonObjectItemData.getJSONObject("kereta");
Kereta kereta = new Kereta();
kereta.setName(jsonObjectKereta.getString("name"));
kereta.setClass_(jsonObjectKereta.getString("class"));
// berangkat
JSONObject jsonObjectBerangkat = jsonObjectItemData.getJSONObject("berangkat");
Berangkat berangkat = new Berangkat();
berangkat.setJam(jsonObjectBerangkat.getString("jam"));
berangkat.setTanggal(jsonObjectBerangkat.getString("tanggal"));
// datang
JSONObject jsonObjectDatang = jsonObjectItemData.getJSONObject("datang");
Datang datang = new Datang();
datang.setJam(jsonObjectDatang.getString("jam"));
datang.setTanggal(jsonObjectDatang.getString("tanggal"));
// durasi
String durasi = jsonObjectItemData.getString("durasi");
if (durasi.split(" ")[0].equalsIgnoreCase("0j")) {
durasi = durasi.split(" ")[1];
}
else if (durasi.split(" ")[1].equalsIgnoreCase("0m")) {
durasi = durasi.split(" ")[0];
}
// harga
JSONObject jsonObjectHarga = jsonObjectItemData.getJSONObject("harga");
Harga harga = new Harga();
harga.setRp(jsonObjectHarga.getString("rp"));
harga.setSubclass(jsonObjectHarga.getString("subclass"));
datum.setKereta(kereta);
datum.setBerangkat(berangkat);
datum.setDatang(datang);
datum.setDurasi(durasi);
datum.setHarga(harga);
datum.setTiket(tiket);
listDatum.add(datum);
}
} catch (JSONException jsone) {
jsone.printStackTrace();
}
}
}
Struktur Projek
Bagi Anda yang masih bingung terhadap pembuatan timeline layout pada tutorial ini silakan bertanya pada komentar. Untuk semua file pendukung projeknya sudah saya upload di akun github saya di sini
0
0
0
share