UPDATE ! 10 Juli 2021. Penambahan repositori Github, dapat dilihat di https://github.com/DaltrayNababan/MovieTracker
Tutorial ini adalah bagian ke-2 dari Aplikasi Movie & TV Shows Menggunakan API TMDB. Bagi Anda yang ingin mengikuti tutorial ini namun belum melihat tutorial bagian 1, silahkan untuk terlebih dahulu melihatnya, Klik Disini. Tutorial tersebut mengenai langkah-langkah mendapatkan API Key TMDB.
Sekarang mari kita buat sebuah project baru dengan minimum SDK 5.0 (21) dan layout empty activity. Pada tutorial ini, aplikasi diberi nama Movie Tracker dengan nama package com.gwnbs.movietracker.
Aplikasi ini akan memiliki fitur yakni menampilkan Most Popular Movies, Now Playing Movies, Upcoming Movies, Top Rated Movies, Most Popular TV Shows, Top Rated TV Shows, On The Air TV Shows, rincian dari movie / tv show, dan pencarian movie / tv show. Berikut video singkat penampakan dari aplikasi.
Disini kita menggunakan Java 8 atau 1.8, sehingga pada build.gradle(app) kita perlu melakukan konfigurasi tambahan. Baik, setelah project Anda sudah dibuat, pertama-tama buka file build.gradle(app) untuk melakukan konfigurasi dan menambahkan beberapa library yang dibutuhkan seperti : Retrofit, Picasso dan RoundedImageView. Pastikan file gradle Anda seperti dibawah ini :
build.gradle(:app) :plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.gwnbs.movietracker"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
//Library bawaan
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
//Library tambahan yang dibutuhkan
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.makeramen:roundedimageview:2.3.0'
}
Setelah itu lakukan sync gradle untuk mulai mengunduh library. Berikutnya resouce value yaitu strings.xml, colors.xml dan themes.xml. Saya harap Anda sudah menggunakan Android Studio versi terbaru saat ini yaitu 4.1.2 agar terhindar dari kendala-kendala, karena cukup banyak perubahan pada versi terbaru ini.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="color_actionbar">#E6E4E4</color>
</resources>
strings.xml :
<resources>
<string name="app_name">Movie Tracker | gwnbs.com</string>
<string name="movies">Movies</string>
<string name="most_popular_movies">Most Popular Movies</string>
<string name="now_playing_movies">Now Playing Movies</string>
<string name="upcoming_movies">Upcoming Movies</string>
<string name="top_rated_movies">Top Rated Movies</string>
<string name="tv_shows">TV Shows</string>
<string name="most_popular_tv_shows">Most Popular TV Shows</string>
<string name="top_rated_tv_shows">Top Rated TV Shows</string>
<string name="on_the_air_tv_shows">On The Air TV Shows</string>
<string name="text_info">Aplikasi ini sepenuhnya menggunakan API dari TMDB (www.themoviedb.org), namun tidak didukung oleh TMDB.</string>
<string name="enter_keyword">Enter query</string>
<string name="no_results">No results</string>
<string name="something_wrong">Something wrong with connection</string>
<string name="search_movie_or_tv_show">Search Movie or TV Show</string>
</resources>
themes.xml :
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MovieTracker" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#454545</item>
<item name="colorPrimaryVariant">#4A4141</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:fontFamily">@font/alegreya_medium</item>
<!-- Customize your theme here. -->
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/color_actionbar"/>
</shape>
bg_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/purple_700">
<item>
<shape android:shape="rectangle">
<solid android:color="#ECEAEA"/>
<corners android:radius="10dp"/>
</shape>
</item>
</ripple>
bg_oval.xml :
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/purple_500">
<item>
<shape android:shape="oval">
<stroke
android:width="1dp"
android:color="@color/black" />
<solid android:color="@color/white" />
</shape>
</item>
</ripple>
bg_text_title.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#D3D0D0"/>
<corners android:radius="15dp"/>
</shape>
bg_view_gradient.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:endColor="#FFFFFF"
android:startColor="@android:color/transparent"/>
</shape>
ic_android.xml :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:tint="#1DA238"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17.6,9.48l1.84,-3.18c0.16,-0.31 0.04,-0.69 -0.26,-0.85c-0.29,-0.15 -0.65,-0.06 -0.83,0.22l-1.88,3.24c-2.86,-1.21 -6.08,-1.21 -8.94,0L5.65,5.67c-0.19,-0.29 -0.58,-0.38 -0.87,-0.2C4.5,5.65 4.41,6.01 4.56,6.3L6.4,9.48C3.3,11.25 1.28,14.44 1,18h22C22.72,14.44 20.7,11.25 17.6,9.48zM7,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25S8.25,13.31 8.25,14C8.25,14.69 7.69,15.25 7,15.25zM17,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25s1.25,0.56 1.25,1.25C18.25,14.69 17.69,15.25 17,15.25z" />
</vector>
ic_back.xml :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="#393939"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>
ic_search.xml :
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:tint="#393939"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
</vector>
Tahap selanjutnya, buatlah 2 buah files java, sebuah java class dan sebuah java interface yang digunakan untuk mengirim permintaan API dari TMDB. Beri nama ApiClient.java dan ApiService.java. Berikut isinya.
package com.gwnbs.movietracker;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static Retrofit retrofit;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("https://api.themoviedb.org/3/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
ApiService.java :
package com.gwnbs.movietracker;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface ApiService {
//Permintaan untuk menampilkan Most Popular Movies
@GET("movie/popular")
Call<MovieRespon> getPopularMovies(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan Now Playing Movies
@GET("movie/now_playing")
Call<MovieRespon> getNowPlayingMovies(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan Upcoming Movies
@GET("movie/upcoming")
Call<MovieRespon> getUpcomingMovies(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan Top Rated Movies
@GET("movie/top_rated")
Call<MovieRespon> getTopRatedMovies(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk pencarian Movie
@GET("search/movie")
Call<MovieRespon> searchMovie(@Query("api_key") String apiKey, @Query("language") String language,
@Query("query") String query, @Query("page") int page);
//Permintaan untuk menampilkan rincian / details movie
@GET("movie/{movie_id}")
Call<MovieDetails> getMovieDetails(@Path("movie_id") String id, @Query("api_key") String apiKey);
//Permintaan untuk menampilkan Most Popular TV Shows
@GET("tv/popular")
Call<TVRespon> getTvPopular(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan Top Rated TV Shows
@GET("tv/top_rated")
Call<TVRespon> getTvTopRated(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan On Air TV Shows
@GET("tv/on_the_air")
Call<TVRespon> getTvOnAir(@Query("api_key") String apiKey, @Query("language") String language,
@Query("page") int page);
//Permintaan untuk menampilkan rincian TV Show
@GET("tv/{tv_id}")
Call<TVDetails> getTvDetails(@Path("tv_id") String id, @Query("api_key") String apiKey);
//Permintaan untuk pencarian TV Shows
@GET("search/tv")
Call<TVRespon> searchTv(@Query("api_key") String apiKey, @Query("language") String language,
@Query("query") String query, @Query("page") int page);
}
package com.gwnbs.movietracker;
import android.widget.ImageView;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
public class ImageAdapter {
public static final String IMAGEBASE_URL = "https://image.tmdb.org/t/p/w220_and_h330_face";
public static final String BACKDROPIMAGE_BASE_URL = "https://image.tmdb.org/t/p/original";
public static void setPosterURL(ImageView imageView, String path) {
try {
imageView.setAlpha(0f);
Picasso.get().load(IMAGEBASE_URL + path).noFade().into(imageView, new Callback() {
@Override
public void onSuccess() {
imageView.animate().setDuration(500).alpha(1f).start();
}
@Override
public void onError(Exception e) {
}
});
} catch (Exception ignored) {
}
}
public static void setBackdropURL(ImageView imageView, String path) {
try {
imageView.setAlpha(0f);
Picasso.get().load(BACKDROPIMAGE_BASE_URL + path).noFade().into(imageView, new Callback() {
@Override
public void onSuccess() {
imageView.animate().setDuration(500).alpha(1f).start();
}
@Override
public void onError(Exception e) {
}
});
} catch (Exception ignored) {
}
}
}
Nah, sekarang buatlah 6 buah java files dengan nama : MovieRespon.java, MovieResult.java, MovieDetails.java, TVRespon.java, TVResult.java dan TVDetails.java. Class-class ini digunakan untuk getter (mendapatkan) nilai-nilai yang kita butuhkan dari database TMDB. Karena kita memuat data dengan streaming maka kita membutuhkan anotasi Serialize.
package com.gwnbs.movietracker;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class MovieRespon {
@SerializedName("page")
int page;
@SerializedName("results")
private final List<MovieResult> results = new ArrayList<>();
@SerializedName("total_results")
int totalResults;
@SerializedName("total_pages")
int totalPages;
public int getPage() {
return page;
}
public List<MovieResult> getResults() {
return results;
}
public int getTotalResults() {
return totalResults;
}
public int getTotalPages() {
return totalPages;
}
}
MovieResult.java :
package com.gwnbs.movietracker;
import com.google.gson.annotations.SerializedName;
public class MovieResult {
@SerializedName("id")
int id;
@SerializedName("poster_path")
String posterPath;
@SerializedName("title")
String title;
public int getId() {
return id;
}
public String getPosterPath() {
return posterPath;
}
public String getTitle() {
return title;
}
}
MovieDetails.java :
package com.gwnbs.movietracker;
import androidx.annotation.Keep;
import com.google.gson.annotations.SerializedName;
@Keep
public class MovieDetails {
@SerializedName("title")
String title;
@SerializedName("homepage")
String homepage;
@SerializedName("overview")
String overview;
@SerializedName("runtime")
String runtime;
@SerializedName("poster_path")
String posterPath;
@SerializedName("vote_average")
String voteAverage;
@SerializedName("release_date")
String releaseDate;
@SerializedName("original_language")
String language;
@SerializedName("backdrop_path")
String backdropPath;
@SerializedName("status")
String status;
@SerializedName("budget")
String budget;
@SerializedName("revenue")
String revenue;
@SerializedName("popularity")
String popularity;
@SerializedName("tagline")
String tagline;
@SerializedName("vote_count")
String voteCount;
public String getStatus() {
return status;
}
public String getHomepage() {
return homepage;
}
public String getOverview() {
return overview;
}
public String getRuntime() {
return runtime;
}
public String getPosterPath() {
return posterPath;
}
public String getVoteAverage() {
return voteAverage;
}
public String getBackdropPath() {
return backdropPath;
}
public String getReleaseDate() {
return releaseDate;
}
public String getBudget() {
return budget;
}
public String getRevenue() {
return revenue;
}
public String getPopularity() {
return popularity;
}
public String getTagline() {
return tagline;
}
public String getVoteCount() {
return voteCount;
}
public String getLanguage() {
return language;
}
public String getTitle() {
return title;
}
}
TVRespon.java :
package com.gwnbs.movietracker;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class TVRespon {
@SerializedName("page")
int page;
@SerializedName("results")
private final List<TVResult> results = new ArrayList<>();
@SerializedName("total_results")
int totalResults;
@SerializedName("total_pages")
int totalPages;
public int getPage() {
return page;
}
public List<TVResult> getResults() {
return results;
}
public int getTotalResults() {
return totalResults;
}
public int getTotalPages() {
return totalPages;
}
}
TVResult.java :
package com.gwnbs.movietracker;
import com.google.gson.annotations.SerializedName;
public class TVResult {
@SerializedName("id")
int id;
@SerializedName("poster_path")
String posterPath;
@SerializedName("original_name")
String name;
public int getId() {
return id;
}
public String getPosterPath() {
return posterPath;
}
public String getName() {
return name;
}
}
TVDetails.java :
package com.gwnbs.movietracker;
import androidx.annotation.Keep;
import com.google.gson.annotations.SerializedName;
@Keep
public class TVDetails {
@SerializedName("name")
String name;
@SerializedName("poster_path")
String posterPath;
@SerializedName("backdrop_path")
String backdropPath;
@SerializedName("episode_run_time")
int[] episodeRuntime;
@SerializedName("first_air_date")
String firstAirDate;
@SerializedName("last_air_date")
String lastAirdate;
@SerializedName("number_of_episodes")
String numberOfEpisodes;
@SerializedName("number_of_seasons")
String numberOfSeasons;
@SerializedName("original_language")
String originalLanguage;
@SerializedName("overview")
String overview;
@SerializedName("popularity")
String popularity;
@SerializedName("status")
String status;
@SerializedName("tagline")
String tagline;
@SerializedName("vote_average")
String voteAverage;
@SerializedName("vote_count")
String voteCount;
@SerializedName("homepage")
String homepage;
public int[] getEpisodeRuntime() {
return episodeRuntime;
}
public String getBackdropPath() {
return backdropPath;
}
public String getFirstAirDate() {
return firstAirDate;
}
public String getLastAirdate() {
return lastAirdate;
}
public String getName() {
return name;
}
public String getNumberOfEpisodes() {
return numberOfEpisodes;
}
public String getNumberOfSeasons() {
return numberOfSeasons;
}
public String getOriginalLanguage() {
return originalLanguage;
}
public String getOverview() {
return overview;
}
public String getPopularity() {
return popularity;
}
public String getPosterPath() {
return posterPath;
}
public String getStatus() {
return status;
}
public String getTagline() {
return tagline;
}
public String getVoteAverage() {
return voteAverage;
}
public String getVoteCount() {
return voteCount;
}
public String getHomepage() {
return homepage;
}
}
<?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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/bg_item"
android:gravity="center"
android:orientation="vertical"
android:padding="3dp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageItemPoster"
android:layout_width="85dp"
android:layout_height="120dp"
android:layout_marginTop="3dp"
android:scaleType="centerCrop"
app:riv_corner_radius="10dp" />
<TextView
android:id="@+id/textItemName"
android:layout_width="85dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:alpha="0.6"
android:gravity="center"
android:lines="2"
android:textColor="@color/black"
android:textSize="10sp"
tools:ignore="SmallSp" />
</LinearLayout>
item_container_search.xml :
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center"
android:orientation="vertical"
android:padding="3dp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/imageItemPoster"
android:layout_width="100dp"
android:layout_height="150dp"
android:layout_marginTop="3dp"
android:background="@drawable/bg_item"
android:scaleType="centerCrop"
app:riv_corner_radius="10dp" />
<TextView
android:id="@+id/textItemName"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:alpha="0.6"
android:gravity="center"
android:lines="2"
android:textColor="@color/black"
android:textSize="10sp"
tools:ignore="SmallSp" />
</LinearLayout>
Sekarang 4 buah file java adapter. Beri nama MovieAdapter.java, MovieSearchAdapter.java, TVAdapter.java dan TVSearchAdapter.java. Ke-4 adapter ini adalah adapter RecyclerView karena memang disini kita hanya memakai RecyclerView. Untuk class list, RecyclerView adalah yang terbaik saat ini.
package com.gwnbs.movietracker;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.makeramen.roundedimageview.RoundedImageView;
import java.util.List;
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private final List<MovieResult> movieResults;
private final Context context;
public MovieAdapter(List<MovieResult> movieResults, Context context) {
this.movieResults = movieResults;
this.context = context;
}
@NonNull
@Override
public MovieAdapter.MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MovieViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_container, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MovieAdapter.MovieViewHolder holder, int position) {
holder.bindItem(movieResults.get(position), context);
}
@Override
public int getItemCount() {
return movieResults.size();
}
static class MovieViewHolder extends RecyclerView.ViewHolder {
private final RoundedImageView imageItemPoster;
private final TextView textItemName;
MovieViewHolder(@NonNull View itemView) {
super(itemView);
imageItemPoster = itemView.findViewById(R.id.imageItemPoster);
textItemName = itemView.findViewById(R.id.textItemName);
}
void bindItem(MovieResult movieResult, Context context) {
if (!TextUtils.isEmpty(movieResult.getPosterPath())) {
ImageAdapter.setPosterURL(imageItemPoster, movieResult.getPosterPath());
} else {
imageItemPoster.setImageResource(R.drawable.ic_android);
}
textItemName.setText(movieResult.getTitle());
itemView.setOnClickListener(v -> {
Intent i = new Intent(context, DetailsActivity.class);
i.putExtra("tipe", "movie");
i.putExtra("id", movieResult.getId());
context.startActivity(i);
});
}
}
}
MovieSearchAdapter.java :
package com.gwnbs.movietracker;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.makeramen.roundedimageview.RoundedImageView;
import java.util.List;
public class MovieSearchAdapter extends RecyclerView.Adapter<MovieSearchAdapter.MovieViewHolder> {
private final List<MovieResult> movieResults;
private final Context context;
public MovieSearchAdapter(List<MovieResult> movieResults, Context context) {
this.movieResults = movieResults;
this.context = context;
}
@NonNull
@Override
public MovieSearchAdapter.MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MovieViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_container_search, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MovieSearchAdapter.MovieViewHolder holder, int position) {
holder.bindItem(movieResults.get(position), context);
}
@Override
public int getItemCount() {
return movieResults.size();
}
static class MovieViewHolder extends RecyclerView.ViewHolder {
private final RoundedImageView imageItemPoster;
private final TextView textItemName;
MovieViewHolder(@NonNull View itemView) {
super(itemView);
imageItemPoster = itemView.findViewById(R.id.imageItemPoster);
textItemName = itemView.findViewById(R.id.textItemName);
}
void bindItem(MovieResult movieResult, Context context) {
if (!TextUtils.isEmpty(movieResult.getPosterPath())) {
ImageAdapter.setPosterURL(imageItemPoster, movieResult.getPosterPath());
} else {
imageItemPoster.setImageResource(R.drawable.ic_android);
}
textItemName.setText(movieResult.getTitle());
itemView.setOnClickListener(v -> {
Intent i = new Intent(context, DetailsActivity.class);
i.putExtra("tipe", "movie");
i.putExtra("id", movieResult.getId());
context.startActivity(i);
});
}
}
}
TVAdapter.java :
package com.gwnbs.movietracker;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.makeramen.roundedimageview.RoundedImageView;
import java.util.List;
public class TVAdapter extends RecyclerView.Adapter<TVAdapter.TvViewHolder> {
private final List<TVResult> TVResults;
private final Context context;
public TVAdapter(List<TVResult> TVResults, Context context) {
this.TVResults = TVResults;
this.context = context;
}
@NonNull
@Override
public TvViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new TvViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_container, parent, false));
}
@Override
public void onBindViewHolder(@NonNull TvViewHolder holder, int position) {
holder.bindItem(TVResults.get(position), context);
}
@Override
public int getItemCount() {
return TVResults.size();
}
static class TvViewHolder extends RecyclerView.ViewHolder {
private final RoundedImageView imageItemPoster;
private final TextView textItemName;
TvViewHolder(@NonNull View itemView) {
super(itemView);
imageItemPoster = itemView.findViewById(R.id.imageItemPoster);
textItemName = itemView.findViewById(R.id.textItemName);
}
void bindItem(TVResult tvResult, Context context) {
if (!TextUtils.isEmpty(tvResult.getPosterPath())) {
ImageAdapter.setPosterURL(imageItemPoster, tvResult.getPosterPath());
} else {
imageItemPoster.setImageResource(R.drawable.ic_android);
}
textItemName.setText(tvResult.getName());
itemView.setOnClickListener(v -> {
Intent i = new Intent(context, DetailsActivity.class);
i.putExtra("tipe", "tv");
i.putExtra("id", tvResult.getId());
context.startActivity(i);
});
}
}
}
TVSearchAdapter.java :
package com.gwnbs.movietracker;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.makeramen.roundedimageview.RoundedImageView;
import java.util.List;
public class TVSearchAdapter extends RecyclerView.Adapter<TVSearchAdapter.TvViewHolder> {
private final List<TVResult> TVResults;
private final Context context;
public TVSearchAdapter(List<TVResult> TVResults, Context context) {
this.TVResults = TVResults;
this.context = context;
}
@NonNull
@Override
public TvViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new TvViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_container_search, parent, false));
}
@Override
public void onBindViewHolder(@NonNull TvViewHolder holder, int position) {
holder.bindItem(TVResults.get(position), context);
}
@Override
public int getItemCount() {
return TVResults.size();
}
static class TvViewHolder extends RecyclerView.ViewHolder {
private final RoundedImageView imageItemPoster;
private final TextView textItemName;
TvViewHolder(@NonNull View itemView) {
super(itemView);
imageItemPoster = itemView.findViewById(R.id.imageItemPoster);
textItemName = itemView.findViewById(R.id.textItemName);
}
void bindItem(TVResult tvResult, Context context) {
if (!TextUtils.isEmpty(tvResult.getPosterPath())) {
ImageAdapter.setPosterURL(imageItemPoster, tvResult.getPosterPath());
} else {
imageItemPoster.setImageResource(R.drawable.ic_android);
}
textItemName.setText(tvResult.getName());
itemView.setOnClickListener(v -> {
Intent i = new Intent(context, DetailsActivity.class);
i.putExtra("tipe", "tv");
i.putExtra("id", tvResult.getId());
context.startActivity(i);
});
}
}
}
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_text_title"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:text="@string/movies"
android:textColor="@color/black"
android:textSize="22sp"
android:textStyle="bold" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/textMoviePopular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/most_popular_movies"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvMoviePopular"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMoviePopular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textMoviePopular" />
<ProgressBar
android:id="@+id/loadingMoviePopular"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMoviePopular"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvMoviePopular" />
<ProgressBar
android:id="@+id/loadingMainMoviePopular"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMoviePopular"
app:layout_constraintEnd_toEndOf="@id/rvMoviePopular"
app:layout_constraintStart_toStartOf="@id/rvMoviePopular"
app:layout_constraintTop_toTopOf="@id/rvMoviePopular" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/textMovieNowPlaying"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/now_playing_movies"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvMovieNowPlaying"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMovieNowPlaying"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textMovieNowPlaying" />
<ProgressBar
android:id="@+id/loadingMovieNowPlaying"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMovieNowPlaying"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvMovieNowPlaying" />
<ProgressBar
android:id="@+id/loadingMainMovieNowPlaying"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMovieNowPlaying"
app:layout_constraintEnd_toEndOf="@id/rvMovieNowPlaying"
app:layout_constraintStart_toStartOf="@id/rvMovieNowPlaying"
app:layout_constraintTop_toTopOf="@id/rvMovieNowPlaying" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/textUpcomingMovie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/upcoming_movies"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvUpcomingMovie"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvUpcomingMovie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textUpcomingMovie" />
<ProgressBar
android:id="@+id/loadingMovieUpcoming"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvUpcomingMovie"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvUpcomingMovie" />
<ProgressBar
android:id="@+id/loadingMainMovieUpcoming"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvUpcomingMovie"
app:layout_constraintEnd_toEndOf="@id/rvUpcomingMovie"
app:layout_constraintStart_toStartOf="@id/rvUpcomingMovie"
app:layout_constraintTop_toTopOf="@id/rvUpcomingMovie" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/textMovieTopRated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/top_rated_movies"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvMovieTopRated"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMovieTopRated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textMovieTopRated" />
<ProgressBar
android:id="@+id/loadingMovieTopRated"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMovieTopRated"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvMovieTopRated" />
<ProgressBar
android:id="@+id/loadingMainMovieTopRated"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvMovieTopRated"
app:layout_constraintEnd_toEndOf="@id/rvMovieTopRated"
app:layout_constraintStart_toStartOf="@id/rvMovieTopRated"
app:layout_constraintTop_toTopOf="@id/rvMovieTopRated" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
layout_tv.xml :
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_text_title"
android:paddingStart="10dp"
android:paddingTop="5dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:text="@string/tv_shows"
android:textColor="@color/black"
android:textSize="22sp"
android:textStyle="bold" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/textTvPopular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/most_popular_tv_shows"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvTvPopular"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvTvPopular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textTvPopular" />
<ProgressBar
android:id="@+id/loadingTvPopular"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvPopular"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvTvPopular" />
<ProgressBar
android:id="@+id/loadingMainTvPopular"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvPopular"
app:layout_constraintEnd_toEndOf="@id/rvTvPopular"
app:layout_constraintStart_toStartOf="@id/rvTvPopular"
app:layout_constraintTop_toTopOf="@id/rvTvPopular" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/textTvTopRated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/top_rated_tv_shows"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvTvTopRated"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvTvTopRated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textTvTopRated" />
<ProgressBar
android:id="@+id/loadingTvTopRated"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvTopRated"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvTvTopRated" />
<ProgressBar
android:id="@+id/loadingMainTvTopRated"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvTopRated"
app:layout_constraintEnd_toEndOf="@id/rvTvTopRated"
app:layout_constraintStart_toStartOf="@id/rvTvTopRated"
app:layout_constraintTop_toTopOf="@id/rvTvTopRated" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/textTvOnAir"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/on_the_air_tv_shows"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@id/rvTvOnAir"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvTvOnAir"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:overScrollMode="never"
android:paddingStart="0dp"
android:paddingEnd="40dp"
android:scrollbars="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/textTvOnAir" />
<ProgressBar
android:id="@+id/loadingTvOnAir"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvOnAir"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/rvTvOnAir" />
<ProgressBar
android:id="@+id/loadingMainTvOnAir"
android:layout_width="50dp"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/rvTvOnAir"
app:layout_constraintEnd_toEndOf="@id/rvTvOnAir"
app:layout_constraintStart_toStartOf="@id/rvTvOnAir"
app:layout_constraintTop_toTopOf="@id/rvTvOnAir" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Nampaknya postingan ini terlalu panjang, sebaiknya kita lanjutkan pada postingan berbeda. Silahkan KLIK DISINI.
0 comments:
Post a Comment