Creacion de nuevas clases y de nuevos xml, funcionamiento de la api de animelist , tambien ya se consume los datos del anime list y ya puedo adaptar el anime, es decir puedo añadir y editar flata por implementar eliminar!
This commit is contained in:
parent
132cdeafc9
commit
1f526aa91e
|
|
@ -4,10 +4,10 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-04-14T15:52:07.015308900Z">
|
<DropdownSelection timestamp="2025-05-14T14:38:01.362664600Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\santi\.android\avd\Pixel_9_Pro.avd" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\santi\.android\avd\Pixel_9_Pro_2.avd" />
|
||||||
</handle>
|
</handle>
|
||||||
</Target>
|
</Target>
|
||||||
</DropdownSelection>
|
</DropdownSelection>
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,26 @@ dependencies {
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.activity)
|
implementation(libs.activity)
|
||||||
implementation(libs.constraintlayout)
|
implementation(libs.constraintlayout)
|
||||||
|
implementation(libs.navigation.fragment)
|
||||||
|
implementation(libs.navigation.ui)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
||||||
|
// Room
|
||||||
|
implementation ("androidx.room:room-runtime:2.6.1")
|
||||||
|
annotationProcessor ("androidx.room:room-compiler:2.6.1")
|
||||||
|
|
||||||
/*Dependecia para usar glide y cargar imagenes mediante url*/
|
/*Dependecia para usar glide y cargar imagenes mediante url*/
|
||||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||||
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
|
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
|
||||||
|
|
||||||
|
// Retrofit para llamadas HTTP
|
||||||
|
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
|
|
||||||
|
// Convertidor Gson (JSON <-> Java)
|
||||||
|
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||||
|
|
||||||
|
// (Opcional) Logging para depurar peticiones
|
||||||
|
implementation ("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<!-- Agregado el permiso de Internet -->
|
<!-- Permiso para internet si tu app lo requiere -->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
|
@ -14,16 +14,29 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.YomiTrack"
|
android:theme="@style/Theme.YomiTrack"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- PANTALLA INICIAL: SplashActivity -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MainActivity"
|
android:name=".ui.fragments.login.SplashActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<!-- LOGIN: alojará login y registro -->
|
||||||
|
<activity
|
||||||
|
android:name=".ui.fragments.login.LoginActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
<!-- APP PRINCIPAL: BottomNavigationView -->
|
||||||
|
<activity
|
||||||
|
android:name=".ui.MainActivity"
|
||||||
|
android:exported="false" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
package com.santiparra.yomitrack.model;
|
|
||||||
|
|
||||||
public class AnimeItem {
|
|
||||||
private String title;
|
|
||||||
private String imageUrl;
|
|
||||||
private int watchedEpisodes;
|
|
||||||
private int totalEpisodes;
|
|
||||||
private double score;
|
|
||||||
private String type;
|
|
||||||
private String status; // Nuevo atributo
|
|
||||||
|
|
||||||
public AnimeItem(String title, String imageUrl, int watchedEpisodes, int totalEpisodes, double score, String type, String status) {
|
|
||||||
this.title = title;
|
|
||||||
this.imageUrl = imageUrl;
|
|
||||||
this.watchedEpisodes = watchedEpisodes;
|
|
||||||
this.totalEpisodes = totalEpisodes;
|
|
||||||
this.score = score;
|
|
||||||
this.type = type;
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getImageUrl() {
|
|
||||||
return imageUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWatchedEpisodes() {
|
|
||||||
return watchedEpisodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalEpisodes() {
|
|
||||||
return totalEpisodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getScore() {
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
package com.santiparra.yomitrack.model; // Ajusta el paquete si necesitas
|
package com.santiparra.yomitrack.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modelo general de ítem para mostrar en secciones del home.
|
||||||
|
* Se usa tanto para anime como manga.
|
||||||
|
*/
|
||||||
public class ItemModel {
|
public class ItemModel {
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private String progress;
|
private String progress;
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
private ContentType contentType; // Anime o Manga
|
private ContentType contentType;
|
||||||
|
|
||||||
public enum ContentType {
|
public enum ContentType {
|
||||||
ANIME,
|
ANIME,
|
||||||
MANGA
|
MANGA
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor completo
|
|
||||||
public ItemModel(String title, String progress, String imageUrl, ContentType contentType) {
|
public ItemModel(String title, String progress, String imageUrl, ContentType contentType) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
|
|
@ -20,7 +22,6 @@ public class ItemModel {
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +38,6 @@ public class ItemModel {
|
||||||
return contentType;
|
return contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters (opcional si quieres mutar los datos después)
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
package com.santiparra.yomitrack.model;
|
package com.santiparra.yomitrack.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modelo de actividad reciente para mostrar acciones de usuario.
|
||||||
|
*/
|
||||||
public class RecentActivityModel {
|
public class RecentActivityModel {
|
||||||
public String user, action, title, time, imageUrl;
|
public String user;
|
||||||
|
public String action;
|
||||||
|
public String title;
|
||||||
|
public String time;
|
||||||
|
public String imageUrl;
|
||||||
|
|
||||||
public RecentActivityModel(String user, String action, String title, String time, String imageUrl) {
|
public RecentActivityModel(String user, String action, String title, String time, String imageUrl) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
package com.santiparra.yomitrack.model;
|
package com.santiparra.yomitrack.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representa una estadística del usuario, usada para barras de progreso.
|
||||||
|
* Incluye categoría, cantidad y porcentaje de completado.
|
||||||
|
*/
|
||||||
public class UserStats {
|
public class UserStats {
|
||||||
private String category;
|
private String category;
|
||||||
private int count;
|
private int count;
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.santiparra.yomitrack.model.adapters.airing;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.santiparra.yomitrack.R;
|
|
||||||
import com.santiparra.yomitrack.model.ItemModel;
|
|
||||||
|
|
||||||
public class AiringViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
public ImageView imageView;
|
|
||||||
public TextView titleTextView;
|
|
||||||
public TextView progressTextView;
|
|
||||||
|
|
||||||
public AiringViewHolder(@NonNull View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
imageView = itemView.findViewById(R.id.mediaImage);
|
|
||||||
titleTextView = itemView.findViewById(R.id.titleTextView);
|
|
||||||
progressTextView = itemView.findViewById(R.id.progressTextView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bind(ItemModel item) {
|
|
||||||
titleTextView.setText(item.getTitle());
|
|
||||||
progressTextView.setText("Progress: " + item.getProgress());
|
|
||||||
|
|
||||||
if (item.getImageUrl() != null && !item.getImageUrl().isEmpty()) {
|
|
||||||
Glide.with(itemView.getContext())
|
|
||||||
.load(item.getImageUrl())
|
|
||||||
.placeholder(R.drawable.placeholder_image)
|
|
||||||
.error(R.drawable.error_image)
|
|
||||||
.into(imageView);
|
|
||||||
} else {
|
|
||||||
imageView.setImageResource(R.drawable.placeholder_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.santiparra.yomitrack.model.adapters.airing;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.santiparra.yomitrack.R;
|
|
||||||
import com.santiparra.yomitrack.model.ItemModel;
|
|
||||||
|
|
||||||
public class AnimeViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
public ImageView imageView;
|
|
||||||
public TextView titleTextView;
|
|
||||||
public TextView progressTextView;
|
|
||||||
|
|
||||||
public AnimeViewHolder(@NonNull View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
imageView = itemView.findViewById(R.id.mediaImage);
|
|
||||||
titleTextView = itemView.findViewById(R.id.titleTextView);
|
|
||||||
progressTextView = itemView.findViewById(R.id.progressTextView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bind(ItemModel item) {
|
|
||||||
titleTextView.setText(item.getTitle());
|
|
||||||
progressTextView.setText("Progress: " + item.getProgress());
|
|
||||||
|
|
||||||
if (item.getImageUrl() != null && !item.getImageUrl().isEmpty()) {
|
|
||||||
Glide.with(itemView.getContext())
|
|
||||||
.load(item.getImageUrl())
|
|
||||||
.placeholder(R.drawable.placeholder_image)
|
|
||||||
.error(R.drawable.error_image)
|
|
||||||
.into(imageView);
|
|
||||||
} else {
|
|
||||||
imageView.setImageResource(R.drawable.placeholder_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,131 +5,174 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
import com.santiparra.yomitrack.model.AnimeItem;
|
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> {
|
public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> {
|
||||||
|
|
||||||
private final List<AnimeItem> animeList;
|
public static final int VIEW_NORMAL = 0;
|
||||||
private final Context context;
|
public static final int VIEW_COMPACT = 1;
|
||||||
private int viewMode = 0;
|
public static final int VIEW_LARGE = 2;
|
||||||
|
|
||||||
public interface OnAnimeRemoveListener {
|
private List<AnimeEntity> animeList;
|
||||||
void onAnimeRemoved(AnimeItem anime);
|
private int viewType;
|
||||||
|
private final OnAnimeClickListener onEditClick;
|
||||||
|
private final OnAnimeClickListener onLongClick;
|
||||||
|
|
||||||
|
// ✅ Constructor optimizado para uso simple
|
||||||
|
public AnimeAdapter(Context context) {
|
||||||
|
this.animeList = new ArrayList<>();
|
||||||
|
this.viewType = VIEW_NORMAL;
|
||||||
|
this.onEditClick = null;
|
||||||
|
this.onLongClick = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnAnimeRemoveListener removeListener;
|
public AnimeAdapter(List<AnimeEntity> animeList, int viewType,
|
||||||
|
OnAnimeClickListener onEditClick,
|
||||||
public void setOnAnimeRemoveListener(OnAnimeRemoveListener listener) {
|
OnAnimeClickListener onLongClick) {
|
||||||
this.removeListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setViewMode(int mode) {
|
|
||||||
this.viewMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnimeAdapter(Context context, List<AnimeItem> animeList) {
|
|
||||||
this.context = context;
|
|
||||||
this.animeList = animeList;
|
this.animeList = animeList;
|
||||||
|
this.viewType = viewType;
|
||||||
|
this.onEditClick = onEditClick;
|
||||||
|
this.onLongClick = onLongClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewType(int viewType) {
|
||||||
|
this.viewType = viewType;
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public AnimeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public AnimeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
int layoutId;
|
int layout = R.layout.item_anime;
|
||||||
switch (viewMode) {
|
if (viewType == VIEW_COMPACT) layout = R.layout.item_anime_compact;
|
||||||
case 1:
|
else if (viewType == VIEW_LARGE) layout = R.layout.item_anime_large;
|
||||||
layoutId = R.layout.item_anime_large; // solo imagen con score y episodios
|
|
||||||
break;
|
View view = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
|
||||||
case 2:
|
|
||||||
layoutId = R.layout.item_anime_compact; // solo texto
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
layoutId = R.layout.item_anime; // imagen + texto
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
View view = LayoutInflater.from(context).inflate(layoutId, parent, false);
|
|
||||||
return new AnimeViewHolder(view);
|
return new AnimeViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull AnimeViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull AnimeViewHolder holder, int position) {
|
||||||
AnimeItem anime = animeList.get(position);
|
AnimeEntity anime = animeList.get(position);
|
||||||
|
|
||||||
if (holder.title != null)
|
String title = anime.getTitle() != null ? anime.getTitle() : "Sin título";
|
||||||
holder.title.setText(anime.getTitle());
|
String status = anime.getStatus() != null ? anime.getStatus() : "";
|
||||||
|
String type = anime.getType() != null ? anime.getType() : "";
|
||||||
|
String imageUrl = anime.getImageUrl();
|
||||||
|
|
||||||
if (holder.progress != null)
|
if (holder.textTitle != null) holder.textTitle.setText(title);
|
||||||
holder.progress.setText("Progress: " + anime.getWatchedEpisodes() + "/" + anime.getTotalEpisodes());
|
|
||||||
|
|
||||||
if (holder.score != null)
|
if (holder.textStatus != null) {
|
||||||
holder.score.setText(String.valueOf(anime.getScore()));
|
String statusText = status + (type.isEmpty() ? "" : " • " + type);
|
||||||
|
holder.textStatus.setText(statusText);
|
||||||
if (holder.type != null)
|
|
||||||
holder.type.setText(anime.getType());
|
|
||||||
|
|
||||||
if (holder.cover != null) {
|
|
||||||
Glide.with(context)
|
|
||||||
.load(anime.getImageUrl())
|
|
||||||
.placeholder(R.drawable.sample_anime_cover)
|
|
||||||
.into(holder.cover);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holder.buttonOptions != null) {
|
if (holder.textProgress != null) {
|
||||||
holder.buttonOptions.setOnClickListener(v -> {
|
String progress = anime.getProgress() + " eps";
|
||||||
PopupMenu popup = new PopupMenu(context, holder.buttonOptions);
|
holder.textProgress.setText(progress);
|
||||||
popup.inflate(R.menu.anime_item_menu);
|
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
|
||||||
int id = item.getItemId();
|
|
||||||
if (id == R.id.action_edit) {
|
|
||||||
Toast.makeText(context, "Edit: " + anime.getTitle(), Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
} else if (id == R.id.action_remove) {
|
|
||||||
int pos = holder.getAdapterPosition();
|
|
||||||
if (pos != RecyclerView.NO_POSITION) {
|
|
||||||
AnimeItem removed = animeList.remove(pos);
|
|
||||||
notifyItemRemoved(pos);
|
|
||||||
if (removeListener != null) {
|
|
||||||
removeListener.onAnimeRemoved(removed);
|
|
||||||
}
|
|
||||||
Toast.makeText(context, "Removed: " + removed.getTitle(), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (holder.textScore != null) {
|
||||||
|
holder.textScore.setText("Score: " + anime.getScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.textType != null) {
|
||||||
|
holder.textType.setText("Tipo: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.imageCover != null && imageUrl != null && !imageUrl.isEmpty()) {
|
||||||
|
Glide.with(holder.itemView.getContext())
|
||||||
|
.load(imageUrl)
|
||||||
|
.placeholder(R.drawable.rectangle_placeholder)
|
||||||
|
.into(holder.imageCover);
|
||||||
|
} else if (holder.imageCover != null) {
|
||||||
|
holder.imageCover.setImageResource(R.drawable.rectangle_placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.statusDot != null) {
|
||||||
|
int colorResId;
|
||||||
|
switch (anime.getStatus()) {
|
||||||
|
case "Completed":
|
||||||
|
colorResId = R.color.status_completed;
|
||||||
|
break;
|
||||||
|
case "Watching":
|
||||||
|
colorResId = R.color.status_watching;
|
||||||
|
break;
|
||||||
|
case "Paused":
|
||||||
|
colorResId = R.color.status_paused;
|
||||||
|
break;
|
||||||
|
case "Dropped":
|
||||||
|
colorResId = R.color.status_dropped;
|
||||||
|
break;
|
||||||
|
case "Planning":
|
||||||
|
default:
|
||||||
|
colorResId = R.color.status_planning;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
holder.statusDot.setBackgroundTintList(
|
||||||
|
ContextCompat.getColorStateList(holder.itemView.getContext(), colorResId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (onEditClick != null) onEditClick.onClick(anime);
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.itemView.setOnLongClickListener(v -> {
|
||||||
|
if (onLongClick != null) {
|
||||||
|
onLongClick.onClick(anime);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return animeList.size();
|
return animeList != null ? animeList.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AnimeViewHolder extends RecyclerView.ViewHolder {
|
@Override
|
||||||
TextView title, progress, score, type;
|
public int getItemViewType(int position) {
|
||||||
ImageView cover, buttonOptions;
|
return viewType;
|
||||||
|
}
|
||||||
|
|
||||||
AnimeViewHolder(View itemView) {
|
public static class AnimeViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
ImageView imageCover;
|
||||||
|
TextView textTitle, textStatus, textProgress, textScore, textType;
|
||||||
|
View statusDot;
|
||||||
|
|
||||||
|
public AnimeViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
title = itemView.findViewById(R.id.textViewTitle);
|
imageCover = itemView.findViewById(R.id.imageCover);
|
||||||
progress = itemView.findViewById(R.id.textViewProgress);
|
textTitle = itemView.findViewById(R.id.textTitle);
|
||||||
score = itemView.findViewById(R.id.textViewScore);
|
textStatus = itemView.findViewById(R.id.textStatus);
|
||||||
type = itemView.findViewById(R.id.textViewType);
|
textProgress = itemView.findViewById(R.id.textProgress);
|
||||||
cover = itemView.findViewById(R.id.imageViewCover);
|
textScore = itemView.findViewById(R.id.textScore);
|
||||||
buttonOptions = itemView.findViewById(R.id.buttonOptions);
|
textType = itemView.findViewById(R.id.textType);
|
||||||
|
statusDot = itemView.findViewById(R.id.statusDot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateList(List<AnimeEntity> newList) {
|
||||||
|
this.animeList = newList;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface OnAnimeClickListener {
|
||||||
|
void onClick(AnimeEntity anime);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
||||||
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
private List<ItemModel> itemList;
|
private List<ItemModel> itemList;
|
||||||
private String sectionTitle; // Para saber si es Airing o no
|
private String sectionTitle;
|
||||||
|
|
||||||
private static final int TYPE_AIRING = 0;
|
private static final int TYPE_AIRING = 0;
|
||||||
private static final int TYPE_ANIME_MANGA = 1;
|
private static final int TYPE_ANIME_MANGA = 1;
|
||||||
|
|
|
||||||
|
|
@ -1,136 +1,162 @@
|
||||||
|
// MangaAdapter.java actualizado con statusDot dinámico
|
||||||
|
|
||||||
package com.santiparra.yomitrack.model.adapters.manga_adapter;
|
package com.santiparra.yomitrack.model.adapters.manga_adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
import com.santiparra.yomitrack.model.AnimeItem;
|
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHolder> {
|
public class MangaAdapter extends RecyclerView.Adapter<MangaAdapter.MangaViewHolder> {
|
||||||
|
|
||||||
private final List<AnimeItem> mangaList;
|
public static final int VIEW_NORMAL = 0;
|
||||||
private final Context context;
|
public static final int VIEW_COMPACT = 1;
|
||||||
private int viewMode = 0;
|
public static final int VIEW_LARGE = 2;
|
||||||
|
|
||||||
public interface OnMangaRemoveListener {
|
private List<MangaEntity> mangaList;
|
||||||
void onMangaRemoved(AnimeItem manga);
|
private int viewType;
|
||||||
}
|
private final OnMangaClickListener onEditClick;
|
||||||
|
private final OnMangaClickListener onLongClick;
|
||||||
|
|
||||||
private OnMangaRemoveListener removeListener;
|
public MangaAdapter(List<MangaEntity> mangaList, int viewType,
|
||||||
|
OnMangaClickListener onEditClick,
|
||||||
public void setOnMangaRemoveListener(OnMangaRemoveListener listener) {
|
OnMangaClickListener onLongClick) {
|
||||||
this.removeListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setViewMode(int mode) {
|
|
||||||
this.viewMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MangaAdapter(Context context, List<AnimeItem> mangaList) {
|
|
||||||
this.context = context;
|
|
||||||
this.mangaList = mangaList;
|
this.mangaList = mangaList;
|
||||||
|
this.viewType = viewType;
|
||||||
|
this.onEditClick = onEditClick;
|
||||||
|
this.onLongClick = onLongClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewType(int viewType) {
|
||||||
|
this.viewType = viewType;
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public MangaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public MangaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
int layoutId;
|
int layout = R.layout.item_manga;
|
||||||
switch (viewMode) {
|
if (viewType == VIEW_COMPACT) layout = R.layout.item_manga_compact;
|
||||||
case 1:
|
else if (viewType == VIEW_LARGE) layout = R.layout.item_manga_large;
|
||||||
layoutId = R.layout.item_anime_large;
|
|
||||||
break;
|
View view = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
|
||||||
case 2:
|
|
||||||
layoutId = R.layout.item_anime_compact;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
layoutId = R.layout.item_anime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
View view = LayoutInflater.from(context).inflate(layoutId, parent, false);
|
|
||||||
return new MangaViewHolder(view);
|
return new MangaViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull MangaViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull MangaViewHolder holder, int position) {
|
||||||
AnimeItem manga = mangaList.get(position);
|
MangaEntity manga = mangaList.get(position);
|
||||||
|
|
||||||
if (holder.title != null)
|
String title = manga.getTitle() != null ? manga.getTitle() : "Sin título";
|
||||||
holder.title.setText(manga.getTitle());
|
String status = manga.getStatus() != null ? manga.getStatus() : "";
|
||||||
|
String type = manga.getType() != null ? manga.getType() : "";
|
||||||
|
String imageUrl = manga.getImageUrl();
|
||||||
|
|
||||||
if (holder.progress != null)
|
if (holder.textTitle != null) holder.textTitle.setText(title);
|
||||||
holder.progress.setText("Progress: " + manga.getWatchedEpisodes() + "/" + manga.getTotalEpisodes());
|
|
||||||
|
|
||||||
if (holder.score != null)
|
if (holder.textStatus != null) {
|
||||||
holder.score.setText(String.valueOf(manga.getScore()));
|
String statusText = status + (type.isEmpty() ? "" : " • " + type);
|
||||||
|
holder.textStatus.setText(statusText);
|
||||||
if (holder.type != null)
|
|
||||||
holder.type.setText(manga.getType());
|
|
||||||
|
|
||||||
if (holder.cover != null) {
|
|
||||||
Glide.with(context)
|
|
||||||
.load(manga.getImageUrl())
|
|
||||||
.placeholder(R.drawable.sample_anime_cover)
|
|
||||||
.into(holder.cover);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holder.buttonOptions != null) {
|
if (holder.textProgress != null) {
|
||||||
holder.buttonOptions.setOnClickListener(v -> {
|
holder.textProgress.setText(manga.getProgress() + " caps");
|
||||||
PopupMenu popup = new PopupMenu(context, holder.buttonOptions);
|
|
||||||
popup.inflate(R.menu.anime_item_menu);
|
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
|
||||||
int id = item.getItemId();
|
|
||||||
if (id == R.id.action_edit) {
|
|
||||||
Toast.makeText(context, "Edit: " + manga.getTitle(), Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
} else if (id == R.id.action_remove) {
|
|
||||||
int pos = holder.getAdapterPosition();
|
|
||||||
if (pos != RecyclerView.NO_POSITION) {
|
|
||||||
AnimeItem removed = mangaList.remove(pos);
|
|
||||||
notifyItemRemoved(pos);
|
|
||||||
if (removeListener != null) {
|
|
||||||
removeListener.onMangaRemoved(removed);
|
|
||||||
}
|
|
||||||
Toast.makeText(context, "Removed: " + removed.getTitle(), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (holder.textScore != null) {
|
||||||
|
holder.textScore.setText("Score: " + manga.getScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.textType != null) {
|
||||||
|
holder.textType.setText("Tipo: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.imageCover != null && imageUrl != null && !imageUrl.isEmpty()) {
|
||||||
|
Glide.with(holder.itemView.getContext())
|
||||||
|
.load(imageUrl)
|
||||||
|
.placeholder(R.drawable.rectangle_placeholder)
|
||||||
|
.into(holder.imageCover);
|
||||||
|
} else if (holder.imageCover != null) {
|
||||||
|
holder.imageCover.setImageResource(R.drawable.rectangle_placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holder.statusDot != null) {
|
||||||
|
int colorResId;
|
||||||
|
switch (manga.getStatus()) {
|
||||||
|
case "Completed":
|
||||||
|
colorResId = R.color.status_completed;
|
||||||
|
break;
|
||||||
|
case "Reading":
|
||||||
|
colorResId = R.color.status_watching;
|
||||||
|
break;
|
||||||
|
case "Paused":
|
||||||
|
colorResId = R.color.status_paused;
|
||||||
|
break;
|
||||||
|
case "Dropped":
|
||||||
|
colorResId = R.color.status_dropped;
|
||||||
|
break;
|
||||||
|
case "Planning":
|
||||||
|
default:
|
||||||
|
colorResId = R.color.status_planning;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
holder.statusDot.setBackgroundTintList(
|
||||||
|
ContextCompat.getColorStateList(holder.itemView.getContext(), colorResId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (onEditClick != null) onEditClick.onClick(manga);
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.itemView.setOnLongClickListener(v -> {
|
||||||
|
if (onLongClick != null) {
|
||||||
|
onLongClick.onClick(manga);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mangaList.size();
|
return mangaList != null ? mangaList.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MangaViewHolder extends RecyclerView.ViewHolder {
|
@Override
|
||||||
TextView title, progress, score, type;
|
public int getItemViewType(int position) {
|
||||||
ImageView cover, buttonOptions;
|
return viewType;
|
||||||
|
}
|
||||||
|
|
||||||
MangaViewHolder(View itemView) {
|
public static class MangaViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
ImageView imageCover;
|
||||||
|
TextView textTitle, textStatus, textProgress, textScore, textType;
|
||||||
|
View statusDot;
|
||||||
|
|
||||||
|
public MangaViewHolder(@NonNull View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
title = itemView.findViewById(R.id.textViewTitle);
|
imageCover = itemView.findViewById(R.id.imageCover);
|
||||||
progress = itemView.findViewById(R.id.textViewProgress);
|
textTitle = itemView.findViewById(R.id.textTitle);
|
||||||
score = itemView.findViewById(R.id.textViewScore);
|
textStatus = itemView.findViewById(R.id.textStatus);
|
||||||
type = itemView.findViewById(R.id.textViewType);
|
textProgress = itemView.findViewById(R.id.textProgress);
|
||||||
cover = itemView.findViewById(R.id.imageViewCover);
|
textScore = itemView.findViewById(R.id.textScore);
|
||||||
buttonOptions = itemView.findViewById(R.id.buttonOptions);
|
textType = itemView.findViewById(R.id.textType);
|
||||||
|
statusDot = itemView.findViewById(R.id.statusDot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public interface OnMangaClickListener {
|
||||||
|
void onClick(MangaEntity manga);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
package com.santiparra.yomitrack.ui;
|
package com.santiparra.yomitrack.ui;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.activity.EdgeToEdge;
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
|
|
@ -19,6 +23,7 @@ import com.santiparra.yomitrack.databinding.ActivityMainBinding;
|
||||||
import com.santiparra.yomitrack.ui.fragments.anime_list.FragmentAnime;
|
import com.santiparra.yomitrack.ui.fragments.anime_list.FragmentAnime;
|
||||||
import com.santiparra.yomitrack.ui.fragments.browse.FragmentBrowse;
|
import com.santiparra.yomitrack.ui.fragments.browse.FragmentBrowse;
|
||||||
import com.santiparra.yomitrack.ui.fragments.home.FragmentHome;
|
import com.santiparra.yomitrack.ui.fragments.home.FragmentHome;
|
||||||
|
import com.santiparra.yomitrack.ui.fragments.login.LoginActivity;
|
||||||
import com.santiparra.yomitrack.ui.fragments.manga_list.FragmentManga;
|
import com.santiparra.yomitrack.ui.fragments.manga_list.FragmentManga;
|
||||||
import com.santiparra.yomitrack.ui.fragments.profile.FragmentProfile;
|
import com.santiparra.yomitrack.ui.fragments.profile.FragmentProfile;
|
||||||
|
|
||||||
|
|
@ -32,29 +37,22 @@ public class MainActivity extends AppCompatActivity {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||||
|
|
||||||
/*We initialize the values*/
|
|
||||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
/*Implementation so that the toolbar does not mess with the status bar*/
|
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(),false);
|
|
||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.getRoot(), (view,insets) ->{
|
ViewCompat.setOnApplyWindowInsetsListener(binding.getRoot(), (view, insets) -> {
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
view.setPadding(0,systemBars.top,0,systemBars.bottom);
|
view.setPadding(0, systemBars.top, 0, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.bottomNavigationView, (view, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(binding.bottomNavigationView, (view, insets) -> {
|
||||||
int bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
int bottomInset = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
|
||||||
|
|
||||||
// Aplica padding interno para que los íconos no queden pegados al borde
|
|
||||||
view.setPadding(0, 0, 0, bottomInset);
|
view.setPadding(0, 0, 0, bottomInset);
|
||||||
|
|
||||||
// Aplica margen negativo externo para que el fondo se expanda visualmente
|
|
||||||
ViewGroup.LayoutParams params = view.getLayoutParams();
|
ViewGroup.LayoutParams params = view.getLayoutParams();
|
||||||
if (params instanceof ViewGroup.MarginLayoutParams) {
|
if (params instanceof ViewGroup.MarginLayoutParams) {
|
||||||
((ViewGroup.MarginLayoutParams) params).bottomMargin = -bottomInset;
|
((ViewGroup.MarginLayoutParams) params).bottomMargin = -bottomInset;
|
||||||
|
|
@ -63,12 +61,12 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*Implementation of bottomNav*/
|
// Fragmento inicial
|
||||||
replaceFragment(new FragmentHome());
|
replaceFragment(new FragmentHome());
|
||||||
|
|
||||||
|
// Navegación inferior
|
||||||
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
|
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
|
||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
|
|
||||||
if (itemId == R.id.home) {
|
if (itemId == R.id.home) {
|
||||||
replaceFragment(new FragmentHome());
|
replaceFragment(new FragmentHome());
|
||||||
} else if (itemId == R.id.profile) {
|
} else if (itemId == R.id.profile) {
|
||||||
|
|
@ -80,20 +78,35 @@ public class MainActivity extends AppCompatActivity {
|
||||||
} else if (itemId == R.id.browse) {
|
} else if (itemId == R.id.browse) {
|
||||||
replaceFragment(new FragmentBrowse());
|
replaceFragment(new FragmentBrowse());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*Implementation of Toolbar*/
|
// Toolbar
|
||||||
toolbar = findViewById(R.id.toolbar);
|
toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||||
|
|
||||||
|
// Botón de perfil
|
||||||
|
ImageView profileIcon = findViewById(R.id.profileIconToolbar);
|
||||||
|
profileIcon.setOnClickListener(v -> {
|
||||||
|
new AlertDialog.Builder(MainActivity.this)
|
||||||
|
.setTitle("Cerrar sesión")
|
||||||
|
.setMessage("¿Deseas cerrar sesión?")
|
||||||
|
.setPositiveButton("Sí", (dialog, which) -> {
|
||||||
|
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||||
|
prefs.edit().remove("current_user_id").apply();
|
||||||
|
startActivity(new Intent(MainActivity.this, LoginActivity.class)
|
||||||
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
|
||||||
|
})
|
||||||
|
.setNegativeButton("Cancelar", null)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replaceFragment(Fragment fragment){
|
private void replaceFragment(Fragment fragment) {
|
||||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||||
fragmentTransaction.replace(R.id.frame_layout, fragment);
|
fragmentTransaction.replace(R.id.frame_layout, fragment);
|
||||||
fragmentTransaction.commit();
|
fragmentTransaction.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.santiparra.yomitrack.ui.fragments.anime_list;
|
package com.santiparra.yomitrack.ui.fragments.anime_list;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
|
@ -8,172 +10,163 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
import com.santiparra.yomitrack.model.AnimeItem;
|
import com.santiparra.yomitrack.api.ApiClient;
|
||||||
|
import com.santiparra.yomitrack.api.ApiService;
|
||||||
|
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||||
import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeAdapter;
|
import com.santiparra.yomitrack.model.adapters.anime_adapter.AnimeAdapter;
|
||||||
|
import com.santiparra.yomitrack.ui.fragments.addanime.AddAnimeFragment;
|
||||||
|
import com.santiparra.yomitrack.ui.fragments.editanime.EditAnimeFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class FragmentAnime extends Fragment {
|
public class FragmentAnime extends Fragment {
|
||||||
|
|
||||||
|
private EditText editSearch;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private EditText editTextFilter;
|
|
||||||
private TextView textViewTitle;
|
|
||||||
private AnimeAdapter adapter;
|
private AnimeAdapter adapter;
|
||||||
|
private ApiService api;
|
||||||
|
private int userId = 1;
|
||||||
|
|
||||||
private final List<AnimeItem> fullAnimeList = new ArrayList<>();
|
private ImageButton btnViewCompact, btnViewNormal, btnViewLarge;
|
||||||
private final List<AnimeItem> filteredAnimeList = new ArrayList<>();
|
private int currentViewType = AnimeAdapter.VIEW_NORMAL;
|
||||||
private String currentStatus = "Watching";
|
private List<AnimeEntity> animeList = new ArrayList<>();
|
||||||
private int currentViewMode = 0;
|
|
||||||
|
|
||||||
private ImageButton buttonGrid, buttonLarge, buttonList;
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_alist, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view,
|
||||||
View view = inflater.inflate(R.layout.fragment_alist, container, false);
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
recyclerView = view.findViewById(R.id.recyclerViewAnimeList);
|
recyclerView = view.findViewById(R.id.recyclerViewAnime);
|
||||||
editTextFilter = view.findViewById(R.id.editTextFilter);
|
btnViewCompact = view.findViewById(R.id.btnViewCompact);
|
||||||
textViewTitle = view.findViewById(R.id.textViewWatching);
|
btnViewNormal = view.findViewById(R.id.btnViewNormal);
|
||||||
ImageView buttonFilterMenu = view.findViewById(R.id.buttonFilterMenu);
|
btnViewLarge = view.findViewById(R.id.btnViewLarge);
|
||||||
buttonGrid = view.findViewById(R.id.buttonViewGrid);
|
FloatingActionButton fabAdd = view.findViewById(R.id.fabAddAnime);
|
||||||
buttonLarge = view.findViewById(R.id.buttonViewLarge);
|
|
||||||
buttonList = view.findViewById(R.id.buttonViewList);
|
|
||||||
|
|
||||||
buttonGrid.setOnClickListener(v -> setLayoutMode(0));
|
editSearch = view.findViewById(R.id.editSearch);
|
||||||
buttonLarge.setOnClickListener(v -> setLayoutMode(1));
|
editSearch.addTextChangedListener(new TextWatcher() {
|
||||||
buttonList.setOnClickListener(v -> setLayoutMode(2));
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
|
||||||
initSampleAnimeList();
|
|
||||||
|
|
||||||
filteredAnimeList.addAll(fullAnimeList);
|
|
||||||
adapter = new AnimeAdapter(getContext(), filteredAnimeList);
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
adapter.setOnAnimeRemoveListener(anime -> fullAnimeList.remove(anime));
|
|
||||||
|
|
||||||
editTextFilter.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
@Override public void afterTextChanged(Editable s) {}
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
filterAnimeList(s.toString());
|
filterAnimeList(s.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<Integer, String> filterMap = new HashMap<>();
|
api = ApiClient.getClient().create(ApiService.class);
|
||||||
filterMap.put(R.id.filter_all, "All");
|
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||||
filterMap.put(R.id.filter_watching, "Watching");
|
userId = prefs.getInt("current_user_id", -1);
|
||||||
filterMap.put(R.id.filter_planning, "Planning");
|
|
||||||
filterMap.put(R.id.filter_paused, "Paused");
|
|
||||||
filterMap.put(R.id.filter_dropped, "Dropped");
|
|
||||||
filterMap.put(R.id.filter_completed, "Completed");
|
|
||||||
|
|
||||||
buttonFilterMenu.setOnClickListener(v -> {
|
// Botones de vista
|
||||||
PopupMenu popup = new PopupMenu(requireContext(), buttonFilterMenu);
|
btnViewCompact.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_COMPACT));
|
||||||
popup.inflate(R.menu.filter_list_menu);
|
btnViewNormal.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_NORMAL));
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
btnViewLarge.setOnClickListener(v -> setViewType(AnimeAdapter.VIEW_LARGE));
|
||||||
String selectedStatus = filterMap.get(item.getItemId());
|
|
||||||
if (selectedStatus != null) {
|
|
||||||
currentStatus = selectedStatus;
|
|
||||||
textViewTitle.setText(currentStatus);
|
|
||||||
filterAnimeList(editTextFilter.getText().toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
setLayoutMode(currentViewMode);
|
fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.frame_layout, new AddAnimeFragment())
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit());
|
||||||
|
|
||||||
return view;
|
fetchAnimeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterAnimeList(String query) {
|
private void filterAnimeList(String query) {
|
||||||
filteredAnimeList.clear();
|
List<AnimeEntity> filtered = new ArrayList<>();
|
||||||
int count = 0;
|
for (AnimeEntity anime : animeList) {
|
||||||
for (AnimeItem anime : fullAnimeList) {
|
if (anime.getTitle().toLowerCase().contains(query.toLowerCase())) {
|
||||||
boolean matchesStatus = currentStatus.equals("All") || anime.getStatus().equalsIgnoreCase(currentStatus);
|
filtered.add(anime);
|
||||||
boolean matchesQuery = anime.getTitle().toLowerCase().contains(query.toLowerCase());
|
|
||||||
if (matchesStatus && matchesQuery) {
|
|
||||||
filteredAnimeList.add(anime);
|
|
||||||
count++;
|
|
||||||
if (count >= 10) {
|
|
||||||
Toast.makeText(requireContext(), "Mostrando los primeros 10 resultados", Toast.LENGTH_SHORT).show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter.notifyDataSetChanged();
|
adapter.updateList(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLayoutMode(int mode) {
|
private void fetchAnimeList() {
|
||||||
currentViewMode = mode;
|
api.getAnimeByUser(userId).enqueue(new Callback<List<AnimeEntity>>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<AnimeEntity>> call,
|
||||||
|
@NonNull Response<List<AnimeEntity>> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
animeList = response.body();
|
||||||
|
setViewType(currentViewType);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getContext(), "Error al cargar animes", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mode == 2) { // Compacta: solo texto
|
@Override
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
public void onFailure(@NonNull Call<List<AnimeEntity>> call, @NonNull Throwable t) {
|
||||||
} else if (mode == 1) { // Imagen grande + info
|
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||||
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 1));
|
}
|
||||||
} else if (mode == 0) { // Lista tipo AniList
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setViewType(int viewType) {
|
||||||
|
currentViewType = viewType;
|
||||||
|
|
||||||
|
if (viewType == AnimeAdapter.VIEW_LARGE) {
|
||||||
|
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||||
|
} else {
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter = new AnimeAdapter(getContext(), filteredAnimeList);
|
adapter = new AnimeAdapter(animeList, viewType,
|
||||||
adapter.setViewMode(mode);
|
this::showEditDialog,
|
||||||
adapter.setOnAnimeRemoveListener(anime -> fullAnimeList.remove(anime));
|
this::deleteAnime);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
|
|
||||||
int defaultTint = ContextCompat.getColor(requireContext(), R.color.textPrimary);
|
|
||||||
int activeTint = ContextCompat.getColor(requireContext(), R.color.activeTint);
|
|
||||||
|
|
||||||
buttonGrid.setColorFilter(mode == 0 ? activeTint : defaultTint);
|
|
||||||
buttonLarge.setColorFilter(mode == 1 ? activeTint : defaultTint);
|
|
||||||
buttonList.setColorFilter(mode == 2 ? activeTint : defaultTint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSampleAnimeList() {
|
private void showEditDialog(AnimeEntity anime) {
|
||||||
fullAnimeList.clear();
|
requireActivity().getSupportFragmentManager()
|
||||||
fullAnimeList.add(new AnimeItem("Aharen-san wa Hakarenai Season 2", "https://cdn.example.com/img1.jpg", 5, 12, 8.5, "TV", "Watching"));
|
.beginTransaction()
|
||||||
fullAnimeList.add(new AnimeItem("Anne Shirley", "https://cdn.example.com/img2.jpg", 5, 24, 7.9, "OVA", "Planning"));
|
.replace(R.id.frame_layout, new EditAnimeFragment(anime))
|
||||||
fullAnimeList.add(new AnimeItem("Ballpark de Tsukamaete!", "https://cdn.example.com/img3.jpg", 5, 12, 9.2, "Movie", "Paused"));
|
.addToBackStack(null)
|
||||||
fullAnimeList.add(new AnimeItem("Bleach: TYBW", "https://cdn.example.com/img4.jpg", 8, 13, 9.0, "TV", "Completed"));
|
.commit();
|
||||||
fullAnimeList.add(new AnimeItem("Chainsaw Man", "https://cdn.example.com/img5.jpg", 1, 12, 8.8, "TV", "Dropped"));
|
|
||||||
fullAnimeList.add(new AnimeItem("Code Geass", "https://cdn.example.com/img6.jpg", 25, 25, 9.5, "TV", "Completed"));
|
|
||||||
fullAnimeList.add(new AnimeItem("Death Note", "https://cdn.example.com/img7.jpg", 37, 37, 9.6, "TV", "Completed"));
|
|
||||||
fullAnimeList.add(new AnimeItem("Erased", "https://cdn.example.com/img8.jpg", 12, 12, 9.0, "TV", "Watching"));
|
|
||||||
fullAnimeList.add(new AnimeItem("Fate/Zero", "https://cdn.example.com/img9.jpg", 13, 13, 9.1, "TV", "Planning"));
|
|
||||||
fullAnimeList.add(new AnimeItem("Gintama", "https://cdn.example.com/img10.jpg", 201, 201, 9.7, "TV", "Paused"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void deleteAnime(AnimeEntity anime) {
|
||||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
api.deleteAnime(anime.getId()).enqueue(new Callback<String>() {
|
||||||
super.onSaveInstanceState(outState);
|
@Override
|
||||||
outState.putString("currentStatus", currentStatus);
|
public void onResponse(Call<String> call, Response<String> response) {
|
||||||
}
|
if (response.isSuccessful()) {
|
||||||
|
Toast.makeText(getContext(), "Anime eliminado", Toast.LENGTH_SHORT).show();
|
||||||
|
fetchAnimeList();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
|
public void onFailure(Call<String> call, Throwable t) {
|
||||||
super.onViewStateRestored(savedInstanceState);
|
Toast.makeText(getContext(), "Fallo de conexión", Toast.LENGTH_SHORT).show();
|
||||||
if (savedInstanceState != null) {
|
}
|
||||||
currentStatus = savedInstanceState.getString("currentStatus", "Watching");
|
});
|
||||||
textViewTitle.setText(currentStatus);
|
|
||||||
filterAnimeList(editTextFilter.getText().toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,18 +1,190 @@
|
||||||
package com.santiparra.yomitrack.ui.fragments.browse;
|
package com.santiparra.yomitrack.ui.fragments.browse;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
|
import com.santiparra.yomitrack.model.ItemModel;
|
||||||
|
import com.santiparra.yomitrack.model.adapters.browser_section_adapter.BrowseGridAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class FragmentBrowse extends Fragment {
|
public class FragmentBrowse extends Fragment {
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater layoutInflater, ViewGroup container,
|
private Spinner spinnerType;
|
||||||
Bundle saveInstanceState){
|
private EditText editTextSearch;
|
||||||
return layoutInflater.inflate(R.layout.fragment_browse,container,false);
|
private LinearLayout sectionContainer;
|
||||||
|
|
||||||
|
private final List<ItemModel> animeList = new ArrayList<>();
|
||||||
|
private final List<ItemModel> mangaList = new ArrayList<>();
|
||||||
|
|
||||||
|
public FragmentBrowse() {
|
||||||
|
super(R.layout.fragment_browse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
spinnerType = view.findViewById(R.id.spinnerType);
|
||||||
|
editTextSearch = view.findViewById(R.id.editTextSearch);
|
||||||
|
sectionContainer = view.findViewById(R.id.sectionContainer);
|
||||||
|
|
||||||
|
View statusBarSpacer = view.findViewById(R.id.statusBarSpacer);
|
||||||
|
int statusBarHeight = getStatusBarHeight();
|
||||||
|
ViewGroup.LayoutParams params = statusBarSpacer.getLayoutParams();
|
||||||
|
params.height = statusBarHeight;
|
||||||
|
statusBarSpacer.setLayoutParams(params);
|
||||||
|
|
||||||
|
Spinner spinnerType = view.findViewById(R.id.spinnerType);
|
||||||
|
|
||||||
|
ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(
|
||||||
|
requireContext(), R.array.media_types, R.layout.item_spinner);
|
||||||
|
spinnerAdapter.setDropDownViewResource(R.layout.item_spinner);
|
||||||
|
spinnerType.setAdapter(spinnerAdapter);
|
||||||
|
|
||||||
|
|
||||||
|
loadSampleData();
|
||||||
|
showSections(animeList);
|
||||||
|
|
||||||
|
spinnerType.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(android.widget.AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
String selected = spinnerType.getSelectedItem().toString();
|
||||||
|
if (selected.equals("Anime")) {
|
||||||
|
showSections(animeList);
|
||||||
|
} else {
|
||||||
|
showSections(mangaList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(android.widget.AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editTextSearch.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
String selected = spinnerType.getSelectedItem().toString();
|
||||||
|
if (selected.equals("Anime")) {
|
||||||
|
showSections(animeList, s.toString());
|
||||||
|
} else {
|
||||||
|
showSections(mangaList, s.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSections(List<ItemModel> source) {
|
||||||
|
showSections(source, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSections(List<ItemModel> source, String query) {
|
||||||
|
sectionContainer.removeAllViews();
|
||||||
|
|
||||||
|
List<ItemModel> trending = new ArrayList<>();
|
||||||
|
List<ItemModel> popular = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < source.size(); i++) {
|
||||||
|
ItemModel item = source.get(i);
|
||||||
|
if (!query.isEmpty() && !item.getTitle().toLowerCase().contains(query.toLowerCase())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i % 2 == 0) trending.add(item);
|
||||||
|
else popular.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trending.isEmpty()) {
|
||||||
|
addSection("Trending Now", trending);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!popular.isEmpty()) {
|
||||||
|
addSection("Popular This Season", popular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSection(String title, List<ItemModel> items) {
|
||||||
|
Context context = requireContext();
|
||||||
|
|
||||||
|
LinearLayout sectionLayout = new LinearLayout(context);
|
||||||
|
sectionLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
sectionLayout.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
sectionLayout.setPadding(0, 0, 0, 24);
|
||||||
|
|
||||||
|
TextView titleView = new TextView(context);
|
||||||
|
titleView.setText(title);
|
||||||
|
titleView.setTextSize(18);
|
||||||
|
titleView.setTypeface(null, Typeface.BOLD);
|
||||||
|
titleView.setTextColor(ContextCompat.getColor(context, R.color.textPrimary));
|
||||||
|
titleView.setPadding(0, 0, 0, 8);
|
||||||
|
sectionLayout.addView(titleView);
|
||||||
|
|
||||||
|
RecyclerView recyclerView = new RecyclerView(context);
|
||||||
|
|
||||||
|
// 🔥 Establecer altura fija para 2 filas (170dp + 12sp de texto aprox + márgenes)
|
||||||
|
int itemHeightPx = (int) (170 * context.getResources().getDisplayMetrics().density);
|
||||||
|
int textHeightPx = (int) (40 * context.getResources().getDisplayMetrics().density);
|
||||||
|
int totalHeight = (itemHeightPx + textHeightPx + 45) * 2;
|
||||||
|
|
||||||
|
|
||||||
|
recyclerView.setLayoutParams(new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT, totalHeight)); // <- altura calculada
|
||||||
|
|
||||||
|
GridLayoutManager layoutManager = new GridLayoutManager(context, 2, RecyclerView.HORIZONTAL, false);
|
||||||
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
|
recyclerView.setAdapter(new BrowseGridAdapter(items));
|
||||||
|
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||||
|
recyclerView.setClipToPadding(false);
|
||||||
|
|
||||||
|
sectionLayout.addView(recyclerView);
|
||||||
|
sectionContainer.addView(sectionLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSampleData() {
|
||||||
|
animeList.clear();
|
||||||
|
mangaList.clear();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 20; i++) {
|
||||||
|
animeList.add(new ItemModel("Anime " + i, i + "/24", "https://example.com/anime" + i + ".jpg", ItemModel.ContentType.ANIME));
|
||||||
|
mangaList.add(new ItemModel("Manga " + i, i + "/120", "https://example.com/manga" + i + ".jpg", ItemModel.ContentType.MANGA));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStatusBarHeight() {
|
||||||
|
int result = 0;
|
||||||
|
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||||
|
if (resourceId > 0) {
|
||||||
|
result = getResources().getDimensionPixelSize(resourceId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragmento principal que muestra secciones de anime/manga y actividad reciente.
|
||||||
|
*/
|
||||||
public class FragmentHome extends Fragment {
|
public class FragmentHome extends Fragment {
|
||||||
|
|
||||||
private final List<RecentActivityModel> fullRecentActivity = new ArrayList<>();
|
private final List<RecentActivityModel> fullRecentActivity = new ArrayList<>();
|
||||||
|
|
@ -36,13 +39,14 @@ public class FragmentHome extends Fragment {
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
// Secciones principales
|
// region Secciones de contenido (Airing, En progreso...)
|
||||||
RecyclerView mainRecyclerView = view.findViewById(R.id.mainRecyclerView);
|
RecyclerView mainRecyclerView = view.findViewById(R.id.mainRecyclerView);
|
||||||
mainRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
mainRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
List<String> sectionTitles = Arrays.asList("Airing", "Anime in Progress", "Manga in Progress");
|
List<String> sectionTitles = Arrays.asList("Airing", "Anime in Progress", "Manga in Progress");
|
||||||
Map<String, List<ItemModel>> sectionItems = new HashMap<>();
|
Map<String, List<ItemModel>> sectionItems = new HashMap<>();
|
||||||
|
|
||||||
|
// Datos simulados de ejemplo
|
||||||
sectionItems.put("Airing", Arrays.asList(
|
sectionItems.put("Airing", Arrays.asList(
|
||||||
new ItemModel("Naruto", "5/220", "https://i.imgur.com/qzWZbL2.jpg", ItemModel.ContentType.ANIME),
|
new ItemModel("Naruto", "5/220", "https://i.imgur.com/qzWZbL2.jpg", ItemModel.ContentType.ANIME),
|
||||||
new ItemModel("Bleach", "100/366", "https://i.imgur.com/I0d1HyA.jpg", ItemModel.ContentType.ANIME),
|
new ItemModel("Bleach", "100/366", "https://i.imgur.com/I0d1HyA.jpg", ItemModel.ContentType.ANIME),
|
||||||
|
|
@ -55,40 +59,26 @@ public class FragmentHome extends Fragment {
|
||||||
sectionItems.put("Anime in Progress", Arrays.asList(
|
sectionItems.put("Anime in Progress", Arrays.asList(
|
||||||
new ItemModel("Attack on Titan", "16/25", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
new ItemModel("Attack on Titan", "16/25", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
||||||
new ItemModel("Jujutsu Kaisen", "10/24", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
new ItemModel("Jujutsu Kaisen", "10/24", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
||||||
new ItemModel("One Piece", "900/1100", "https://i.imgur.com/VgVfG6K.jpg", ItemModel.ContentType.ANIME),
|
new ItemModel("One Piece", "900/1100", "https://i.imgur.com/VgVfG6K.jpg", ItemModel.ContentType.ANIME)
|
||||||
new ItemModel("Boruto", "10/100", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
|
||||||
new ItemModel("Dragon Ball", "80/150", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
|
||||||
new ItemModel("Another", "2/12", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME)
|
|
||||||
));
|
));
|
||||||
|
|
||||||
sectionItems.put("Manga in Progress", Arrays.asList(
|
sectionItems.put("Manga in Progress", Arrays.asList(
|
||||||
new ItemModel("Chainsaw Man", "45/100", "https://i.imgur.com/7tZ0h8R.jpg", ItemModel.ContentType.MANGA),
|
new ItemModel("Chainsaw Man", "45/100", "https://i.imgur.com/7tZ0h8R.jpg", ItemModel.ContentType.MANGA),
|
||||||
new ItemModel("Berserk", "370/380", "https://i.imgur.com/8FJYYHo.jpg", ItemModel.ContentType.MANGA),
|
new ItemModel("Berserk", "370/380", "https://i.imgur.com/8FJYYHo.jpg", ItemModel.ContentType.MANGA)
|
||||||
new ItemModel("One Piece", "900/1100", "https://i.imgur.com/VgVfG6K.jpg", ItemModel.ContentType.ANIME),
|
|
||||||
new ItemModel("Boruto", "10/100", "https://i.imgur.com/lWhD6Zc.jpg", ItemModel.ContentType.ANIME),
|
|
||||||
new ItemModel("Dragon Ball", "80/150", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME),
|
|
||||||
new ItemModel("Another", "2/12", "https://i.imgur.com/z4d4kWk.jpg", ItemModel.ContentType.ANIME)
|
|
||||||
));
|
));
|
||||||
|
|
||||||
SectionAdapter sectionAdapter = new SectionAdapter(sectionTitles, sectionItems);
|
SectionAdapter sectionAdapter = new SectionAdapter(sectionTitles, sectionItems);
|
||||||
mainRecyclerView.setAdapter(sectionAdapter);
|
mainRecyclerView.setAdapter(sectionAdapter);
|
||||||
|
// endregion
|
||||||
|
|
||||||
// Actividades recientes
|
// region Actividad reciente
|
||||||
RecyclerView activityRecyclerView = view.findViewById(R.id.activityRecyclerView);
|
RecyclerView activityRecyclerView = view.findViewById(R.id.activityRecyclerView);
|
||||||
activityRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
activityRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
fullRecentActivity.addAll(Arrays.asList(
|
fullRecentActivity.addAll(Arrays.asList(
|
||||||
new RecentActivityModel("Midca", "Read chapters 1 - 60 of", "Choujun! Choujou Senpai", "4 minutes ago", "https://i.imgur.com/7tZ0h8R.jpg"),
|
new RecentActivityModel("Midca", "Read chapters 1 - 60 of", "Choujun! Choujou Senpai", "4 minutes ago", "https://i.imgur.com/7tZ0h8R.jpg"),
|
||||||
new RecentActivityModel("prtrncyon", "Scored 9/10 on", "Chainsaw Man", "12 hours ago", "https://cdn.myanimelist.net/images/manga/2/253146.jpg"),
|
new RecentActivityModel("prtrncyon", "Scored 9/10 on", "Chainsaw Man", "12 hours ago", "https://cdn.myanimelist.net/images/manga/2/253146.jpg")
|
||||||
new RecentActivityModel("BtwIsSanti", "Watched episode 7 of", "Fate/Zero", "1 day ago", "https://cdn.myanimelist.net/images/anime/5/73245.jpg"),
|
// ... más datos simulados aquí
|
||||||
new RecentActivityModel("Taku", "Watched episode 3 of", "Mob Psycho 100", "2 days ago", "https://i.imgur.com/I0d1HyA.jpg"),
|
|
||||||
new RecentActivityModel("Maki", "Read chapter 14 of", "Blue Period", "4 days ago", "https://i.imgur.com/z4d4kWk.jpg"),
|
|
||||||
new RecentActivityModel("Yato", "Scored 10/10 on", "Noragami", "5 days ago", "https://i.imgur.com/8FJYYHo.jpg"),
|
|
||||||
new RecentActivityModel("Eri", "Completed", "My Dress-Up Darling", "6 days ago", "https://i.imgur.com/qzWZbL2.jpg"),
|
|
||||||
new RecentActivityModel("Yuji", "Watched episode 6 of", "Jujutsu Kaisen", "7 days ago", "https://i.imgur.com/lWhD6Zc.jpg"),
|
|
||||||
new RecentActivityModel("Light", "Scored 10/10 on", "Death Note", "8 days ago", "https://i.imgur.com/I0d1HyA.jpg"),
|
|
||||||
new RecentActivityModel("Luffy", "Watched episode 1000 of", "One Piece", "9 days ago", "https://i.imgur.com/VgVfG6K.jpg"),
|
|
||||||
new RecentActivityModel("Gon", "Started watching", "Hunter x Hunter", "10 days ago", "https://i.imgur.com/z4d4kWk.jpg")
|
|
||||||
));
|
));
|
||||||
|
|
||||||
visibleRecentActivity.addAll(fullRecentActivity.subList(0, Math.min(10, fullRecentActivity.size())));
|
visibleRecentActivity.addAll(fullRecentActivity.subList(0, Math.min(10, fullRecentActivity.size())));
|
||||||
|
|
@ -98,6 +88,7 @@ public class FragmentHome extends Fragment {
|
||||||
Button buttonShowMore = view.findViewById(R.id.buttonShowMoreActivity);
|
Button buttonShowMore = view.findViewById(R.id.buttonShowMoreActivity);
|
||||||
Button buttonShowLess = view.findViewById(R.id.buttonShowLessActivity);
|
Button buttonShowLess = view.findViewById(R.id.buttonShowLessActivity);
|
||||||
|
|
||||||
|
// Mostrar más/menos actividad
|
||||||
if (fullRecentActivity.size() > 10) {
|
if (fullRecentActivity.size() > 10) {
|
||||||
buttonShowMore.setVisibility(View.VISIBLE);
|
buttonShowMore.setVisibility(View.VISIBLE);
|
||||||
buttonShowLess.setVisibility(View.GONE);
|
buttonShowLess.setVisibility(View.GONE);
|
||||||
|
|
@ -121,5 +112,6 @@ public class FragmentHome extends Fragment {
|
||||||
buttonShowMore.setVisibility(View.GONE);
|
buttonShowMore.setVisibility(View.GONE);
|
||||||
buttonShowLess.setVisibility(View.GONE);
|
buttonShowLess.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
// endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,174 +1,115 @@
|
||||||
package com.santiparra.yomitrack.ui.fragments.manga_list;
|
package com.santiparra.yomitrack.ui.fragments.manga_list;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
import com.santiparra.yomitrack.model.AnimeItem;
|
import com.santiparra.yomitrack.api.ApiClient;
|
||||||
|
import com.santiparra.yomitrack.api.ApiService;
|
||||||
|
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||||
import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaAdapter;
|
import com.santiparra.yomitrack.model.adapters.manga_adapter.MangaAdapter;
|
||||||
|
import com.santiparra.yomitrack.ui.fragments.addmanga.AddMangaFragment;
|
||||||
|
import com.santiparra.yomitrack.ui.fragments.editmanga.EditMangaFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class FragmentManga extends Fragment {
|
public class FragmentManga extends Fragment {
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private EditText editTextFilter;
|
|
||||||
private TextView textViewTitle;
|
|
||||||
private MangaAdapter adapter;
|
private MangaAdapter adapter;
|
||||||
|
private ApiService api;
|
||||||
|
private int currentViewType = MangaAdapter.VIEW_NORMAL;
|
||||||
|
private int userId = 1; // Deberías usar SharedPreferences si tienes login
|
||||||
|
|
||||||
private final List<AnimeItem> fullMangaList = new ArrayList<>();
|
@Nullable
|
||||||
private final List<AnimeItem> filteredMangaList = new ArrayList<>();
|
|
||||||
private String currentStatus = "Reading";
|
|
||||||
private int currentViewMode = 0;
|
|
||||||
|
|
||||||
private ImageButton buttonGrid, buttonLarge, buttonList;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_alist, container, false);
|
View view = inflater.inflate(R.layout.fragment_mlist, container, false);
|
||||||
|
|
||||||
recyclerView = view.findViewById(R.id.recyclerViewAnimeList);
|
recyclerView = view.findViewById(R.id.recyclerViewManga);
|
||||||
editTextFilter = view.findViewById(R.id.editTextFilter);
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
textViewTitle = view.findViewById(R.id.textViewWatching);
|
|
||||||
ImageView buttonFilterMenu = view.findViewById(R.id.buttonFilterMenu);
|
|
||||||
buttonGrid = view.findViewById(R.id.buttonViewGrid);
|
|
||||||
buttonLarge = view.findViewById(R.id.buttonViewLarge);
|
|
||||||
buttonList = view.findViewById(R.id.buttonViewList);
|
|
||||||
|
|
||||||
buttonGrid.setOnClickListener(v -> setLayoutMode(0));
|
ImageView changeViewButton = view.findViewById(R.id.buttonChangeViewType);
|
||||||
buttonLarge.setOnClickListener(v -> setLayoutMode(1));
|
FloatingActionButton fabAdd = view.findViewById(R.id.fabAddManga);
|
||||||
buttonList.setOnClickListener(v -> setLayoutMode(2));
|
|
||||||
|
|
||||||
initSampleMangaList();
|
api = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
filteredMangaList.addAll(fullMangaList);
|
changeViewButton.setOnClickListener(v -> {
|
||||||
adapter = new MangaAdapter(getContext(), filteredMangaList);
|
currentViewType = (currentViewType + 1) % 3;
|
||||||
recyclerView.setAdapter(adapter);
|
if (adapter != null) adapter.setViewType(currentViewType);
|
||||||
adapter.setOnMangaRemoveListener(manga -> fullMangaList.remove(manga));
|
|
||||||
|
|
||||||
editTextFilter.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
@Override public void afterTextChanged(Editable s) {}
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
filterMangaList(s.toString());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<Integer, String> filterMap = new HashMap<>();
|
fabAdd.setOnClickListener(v -> requireActivity().getSupportFragmentManager()
|
||||||
filterMap.put(R.id.filter_all, "All");
|
.beginTransaction()
|
||||||
filterMap.put(R.id.filter_watching, "Reading");
|
.replace(R.id.frame_layout, new AddMangaFragment())
|
||||||
filterMap.put(R.id.filter_planning, "Planning");
|
.addToBackStack(null)
|
||||||
filterMap.put(R.id.filter_paused, "Paused");
|
.commit());
|
||||||
filterMap.put(R.id.filter_dropped, "Dropped");
|
|
||||||
filterMap.put(R.id.filter_completed, "Completed");
|
|
||||||
|
|
||||||
buttonFilterMenu.setOnClickListener(v -> {
|
loadMangaList();
|
||||||
PopupMenu popup = new PopupMenu(requireContext(), buttonFilterMenu);
|
|
||||||
popup.inflate(R.menu.filter_list_menu);
|
|
||||||
popup.setOnMenuItemClickListener(item -> {
|
|
||||||
String selectedStatus = filterMap.get(item.getItemId());
|
|
||||||
if (selectedStatus != null) {
|
|
||||||
currentStatus = selectedStatus;
|
|
||||||
textViewTitle.setText(currentStatus);
|
|
||||||
filterMangaList(editTextFilter.getText().toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
popup.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
setLayoutMode(currentViewMode);
|
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterMangaList(String query) {
|
private void loadMangaList() {
|
||||||
filteredMangaList.clear();
|
api.getMangaByUser(userId).enqueue(new Callback<List<MangaEntity>>() {
|
||||||
int count = 0;
|
@Override
|
||||||
for (AnimeItem manga : fullMangaList) {
|
public void onResponse(Call<List<MangaEntity>> call, Response<List<MangaEntity>> response) {
|
||||||
boolean matchesStatus = currentStatus.equals("All") || manga.getStatus().equalsIgnoreCase(currentStatus);
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
boolean matchesQuery = manga.getTitle().toLowerCase().contains(query.toLowerCase());
|
adapter = new MangaAdapter(response.body(), currentViewType,
|
||||||
if (matchesStatus && matchesQuery) {
|
FragmentManga.this::showEditDialog,
|
||||||
filteredMangaList.add(manga);
|
FragmentManga.this::deleteManga);
|
||||||
count++;
|
recyclerView.setAdapter(adapter);
|
||||||
if (count >= 10) {
|
} else {
|
||||||
Toast.makeText(requireContext(), "Mostrando los primeros 10 resultados", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Error al cargar la lista", Toast.LENGTH_SHORT).show();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged();
|
@Override
|
||||||
|
public void onFailure(Call<List<MangaEntity>> call, Throwable t) {
|
||||||
|
Toast.makeText(getContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLayoutMode(int mode) {
|
private void showEditDialog(MangaEntity manga) {
|
||||||
currentViewMode = mode;
|
requireActivity().getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
if (mode == 2) {
|
.replace(R.id.frame_layout, new EditMangaFragment(manga))
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
.addToBackStack(null)
|
||||||
} else if (mode == 1) {
|
.commit();
|
||||||
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 1));
|
|
||||||
} else if (mode == 0) {
|
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter = new MangaAdapter(getContext(), filteredMangaList);
|
|
||||||
adapter.setViewMode(mode);
|
|
||||||
adapter.setOnMangaRemoveListener(manga -> fullMangaList.remove(manga));
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
|
|
||||||
int defaultTint = ContextCompat.getColor(requireContext(), R.color.textPrimary);
|
|
||||||
int activeTint = ContextCompat.getColor(requireContext(), R.color.activeTint);
|
|
||||||
|
|
||||||
buttonGrid.setColorFilter(mode == 0 ? activeTint : defaultTint);
|
|
||||||
buttonLarge.setColorFilter(mode == 1 ? activeTint : defaultTint);
|
|
||||||
buttonList.setColorFilter(mode == 2 ? activeTint : defaultTint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSampleMangaList() {
|
private void deleteManga(MangaEntity manga) {
|
||||||
fullMangaList.clear();
|
api.deleteManga(manga.getId()).enqueue(new Callback<String>() {
|
||||||
fullMangaList.add(new AnimeItem("Chainsaw Man", "https://cdn.example.com/img1.jpg", 45, 100, 8.5, "Manga", "Reading"));
|
@Override
|
||||||
fullMangaList.add(new AnimeItem("Berserk", "https://cdn.example.com/img2.jpg", 370, 380, 9.4, "Manga", "Paused"));
|
public void onResponse(Call<String> call, Response<String> response) {
|
||||||
fullMangaList.add(new AnimeItem("One Piece", "https://cdn.example.com/img3.jpg", 1090, 1200, 9.8, "Manga", "Reading"));
|
if (response.isSuccessful()) {
|
||||||
fullMangaList.add(new AnimeItem("Attack on Titan", "https://cdn.example.com/img4.jpg", 139, 139, 9.5, "Manga", "Completed"));
|
Toast.makeText(getContext(), "Manga eliminado", Toast.LENGTH_SHORT).show();
|
||||||
fullMangaList.add(new AnimeItem("Solo Leveling", "https://cdn.example.com/img5.jpg", 179, 179, 8.9, "Manhwa", "Completed"));
|
loadMangaList();
|
||||||
}
|
} else {
|
||||||
|
Toast.makeText(getContext(), "Error al eliminar", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
public void onFailure(Call<String> call, Throwable t) {
|
||||||
super.onSaveInstanceState(outState);
|
Toast.makeText(getContext(), "Fallo en la conexión", Toast.LENGTH_SHORT).show();
|
||||||
outState.putString("currentStatus", currentStatus);
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewStateRestored(savedInstanceState);
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
currentStatus = savedInstanceState.getString("currentStatus", "Reading");
|
|
||||||
textViewTitle.setText(currentStatus);
|
|
||||||
filterMangaList(editTextFilter.getText().toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,166 +1,140 @@
|
||||||
package com.santiparra.yomitrack.ui.fragments.profile;
|
package com.santiparra.yomitrack.ui.fragments.profile;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.santiparra.yomitrack.R;
|
import com.santiparra.yomitrack.R;
|
||||||
import com.santiparra.yomitrack.model.UserStats;
|
import com.santiparra.yomitrack.api.ApiClient;
|
||||||
import com.santiparra.yomitrack.utils.StatsHelper;
|
import com.santiparra.yomitrack.api.ApiService;
|
||||||
|
import com.santiparra.yomitrack.db.entities.AnimeEntity;
|
||||||
|
import com.santiparra.yomitrack.db.entities.MangaEntity;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class FragmentProfile extends Fragment {
|
public class FragmentProfile extends Fragment {
|
||||||
|
|
||||||
public FragmentProfile() {
|
private TextView textUsername;
|
||||||
}
|
private LinearLayout animeStatsContainer, mangaStatsContainer;
|
||||||
|
private ApiService api;
|
||||||
|
private int userId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
Bundle savedInstanceState) {
|
View view = inflater.inflate(R.layout.fragment_profile, container, false);
|
||||||
return inflater.inflate(R.layout.fragment_profile, container, false);
|
|
||||||
|
textUsername = view.findViewById(R.id.usernameText);
|
||||||
|
animeStatsContainer = view.findViewById(R.id.animeStatsContainer);
|
||||||
|
mangaStatsContainer = view.findViewById(R.id.mangaStatsContainer);
|
||||||
|
api = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
SharedPreferences prefs = requireContext().getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||||
|
userId = prefs.getInt("current_user_id", -1);
|
||||||
|
|
||||||
|
if (userId == -1) {
|
||||||
|
textUsername.setText("Invitado");
|
||||||
|
Toast.makeText(getContext(), "Estadísticas no disponibles en modo invitado", Toast.LENGTH_SHORT).show();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
textUsername.setText("Usuario #" + userId);
|
||||||
|
|
||||||
|
loadStats();
|
||||||
|
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void loadStats() {
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
animeStatsContainer.removeAllViews();
|
||||||
super.onViewCreated(view, savedInstanceState);
|
mangaStatsContainer.removeAllViews();
|
||||||
|
|
||||||
TextView usernameText = view.findViewById(R.id.usernameText);
|
api.getAnimeByUser(userId).enqueue(new Callback<List<AnimeEntity>>() {
|
||||||
TextView descriptionText = view.findViewById(R.id.profileDescriptionText);
|
@Override
|
||||||
TextView seeMore = view.findViewById(R.id.textViewSeeMore);
|
public void onResponse(Call<List<AnimeEntity>> call, Response<List<AnimeEntity>> response) {
|
||||||
LinearLayout statsContainer = view.findViewById(R.id.animeStatsContainer);
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
showStats(animeStatsContainer, "Anime", countByStatus(response.body()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
usernameText.setText("BtwIsSanti");
|
@Override
|
||||||
descriptionText.setText("Eiko is my waifu right now. Mai and Mikasa is my second wife. Long live anime.");
|
public void onFailure(Call<List<AnimeEntity>> call, Throwable t) {
|
||||||
|
Toast.makeText(getContext(), "Error al cargar anime", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
seeMore.setOnClickListener(v -> {
|
|
||||||
if (descriptionText.getMaxLines() == 2) {
|
|
||||||
descriptionText.setMaxLines(Integer.MAX_VALUE);
|
|
||||||
descriptionText.setEllipsize(null);
|
|
||||||
seeMore.setText("Ver menos");
|
|
||||||
} else {
|
|
||||||
descriptionText.setMaxLines(2);
|
|
||||||
descriptionText.setEllipsize(TextUtils.TruncateAt.END);
|
|
||||||
seeMore.setText("Ver más");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cargar estadísticas simuladas
|
api.getMangaByUser(userId).enqueue(new Callback<List<MangaEntity>>() {
|
||||||
List<UserStats> statsList = StatsHelper.getAnimeStats();
|
@Override
|
||||||
|
public void onResponse(Call<List<MangaEntity>> call, Response<List<MangaEntity>> response) {
|
||||||
for (UserStats stat : statsList) {
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
View statView = LayoutInflater.from(getContext())
|
showStats(mangaStatsContainer, "Manga", countByStatus(response.body()));
|
||||||
.inflate(R.layout.item_stat_bar, statsContainer, false);
|
}
|
||||||
|
|
||||||
TextView label = statView.findViewById(R.id.statLabelFull);
|
|
||||||
ProgressBar bar = statView.findViewById(R.id.statProgressBar);
|
|
||||||
|
|
||||||
label.setText(stat.getCategory() + " • " + stat.getCount());
|
|
||||||
bar.setProgress(stat.getPercentage());
|
|
||||||
|
|
||||||
// Aplicar color distinto por categoría
|
|
||||||
int colorRes = R.color.primary; // default
|
|
||||||
switch (stat.getCategory()) {
|
|
||||||
case "Watching":
|
|
||||||
colorRes = R.color.statWatching;
|
|
||||||
break;
|
|
||||||
case "Completed":
|
|
||||||
colorRes = R.color.statCompleted;
|
|
||||||
break;
|
|
||||||
case "On Hold":
|
|
||||||
colorRes = R.color.statOnHold;
|
|
||||||
break;
|
|
||||||
case "Dropped":
|
|
||||||
colorRes = R.color.statDropped;
|
|
||||||
break;
|
|
||||||
case "Plan to Watch":
|
|
||||||
colorRes = R.color.statPlanToWatch;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bar.setProgressTintList(ContextCompat.getColorStateList(requireContext(), colorRes));
|
@Override
|
||||||
statsContainer.addView(statView);
|
public void onFailure(Call<List<MangaEntity>> call, Throwable t) {
|
||||||
|
Toast.makeText(getContext(), "Error al cargar manga", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Integer> countByStatus(List<?> items) {
|
||||||
|
Map<String, Integer> counts = new HashMap<>();
|
||||||
|
for (Object item : items) {
|
||||||
|
String status = "";
|
||||||
|
if (item instanceof AnimeEntity) {
|
||||||
|
status = ((AnimeEntity) item).getStatus();
|
||||||
|
} else if (item instanceof MangaEntity) {
|
||||||
|
status = ((MangaEntity) item).getStatus();
|
||||||
|
}
|
||||||
|
counts.put(status, counts.getOrDefault(status, 0) + 1);
|
||||||
}
|
}
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
// Agregar tarjetas de actividad (opcional)
|
private void showStats(LinearLayout container, String category, Map<String, Integer> data) {
|
||||||
LinearLayout activityContainer = view.findViewById(R.id.activityContainer);
|
TextView title = new TextView(getContext());
|
||||||
|
title.setText(category.toUpperCase());
|
||||||
|
title.setTextSize(18);
|
||||||
|
title.setPadding(0, 24, 0, 12);
|
||||||
|
container.addView(title);
|
||||||
|
|
||||||
if (activityContainer != null) {
|
int total = 0;
|
||||||
// Lista simulada de updates
|
for (int count : data.values()) total += count;
|
||||||
String[] activities = {
|
|
||||||
"Watched episode 5 of Kakushite! Makina-san!!",
|
|
||||||
"Watched episode 5 of Chotto dake Ai ga Omo...",
|
|
||||||
"Watched episode 4 of Go-Toubun no Hanayome",
|
|
||||||
"Watched episode 3 of Kanojo, Okarishimasu",
|
|
||||||
"Watched episode 12 of Jujutsu Kaisen",
|
|
||||||
"Watched episode 8 of Bleach: TYBW",
|
|
||||||
"Watched episode 1 of Chainsaw Man",
|
|
||||||
"Watched episode 10 of Dr. Stone",
|
|
||||||
"Watched episode 9 of Mushoku Tensei",
|
|
||||||
"Watched episode 11 of Ousama Ranking",
|
|
||||||
"Watched episode 7 of HUNTER×HUNTER"
|
|
||||||
};
|
|
||||||
|
|
||||||
int limit = Math.min(10, activities.length);
|
for (Map.Entry<String, Integer> entry : data.entrySet()) {
|
||||||
|
String status = entry.getKey();
|
||||||
|
int count = entry.getValue();
|
||||||
|
int percent = (int) ((count / (float) total) * 100);
|
||||||
|
|
||||||
for (int i = 0; i < limit; i++) {
|
TextView label = new TextView(getContext());
|
||||||
View card = LayoutInflater.from(getContext())
|
label.setText(status + ": " + count + " (" + percent + "%)");
|
||||||
.inflate(R.layout.item_activity, activityContainer, false);
|
label.setTextSize(16);
|
||||||
|
container.addView(label);
|
||||||
|
|
||||||
TextView text = card.findViewById(R.id.activityText);
|
ProgressBar progress = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleHorizontal);
|
||||||
TextView time = card.findViewById(R.id.activityTime);
|
progress.setMax(100);
|
||||||
|
progress.setProgress(percent);
|
||||||
text.setText(activities[i]);
|
progress.setLayoutParams(new LinearLayout.LayoutParams(
|
||||||
time.setText("16 hours ago");
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
activityContainer.addView(card);
|
));
|
||||||
}
|
container.addView(progress);
|
||||||
}
|
|
||||||
|
|
||||||
// Estadísticas de manga
|
|
||||||
LinearLayout mangaStatsContainer = view.findViewById(R.id.mangaStatsContainer);
|
|
||||||
List<UserStats> mangaStats = StatsHelper.getMangaStats();
|
|
||||||
|
|
||||||
for (UserStats stat : mangaStats) {
|
|
||||||
View statView = LayoutInflater.from(getContext())
|
|
||||||
.inflate(R.layout.item_stat_bar, mangaStatsContainer, false);
|
|
||||||
|
|
||||||
TextView label = statView.findViewById(R.id.statLabelFull);
|
|
||||||
ProgressBar bar = statView.findViewById(R.id.statProgressBar);
|
|
||||||
|
|
||||||
label.setText(stat.getCategory() + " • " + stat.getCount());
|
|
||||||
bar.setProgress(stat.getPercentage());
|
|
||||||
|
|
||||||
int colorRes = R.color.primary;
|
|
||||||
switch (stat.getCategory()) {
|
|
||||||
case "Reading":
|
|
||||||
colorRes = R.color.statWatching;
|
|
||||||
break;
|
|
||||||
case "Completed":
|
|
||||||
colorRes = R.color.statCompleted;
|
|
||||||
break;
|
|
||||||
case "On Hold":
|
|
||||||
colorRes = R.color.statOnHold;
|
|
||||||
break;
|
|
||||||
case "Dropped":
|
|
||||||
colorRes = R.color.statDropped;
|
|
||||||
break;
|
|
||||||
case "Plan to Read":
|
|
||||||
colorRes = R.color.statPlanToWatch;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bar.setProgressTintList(ContextCompat.getColorStateList(requireContext(), colorRes));
|
|
||||||
mangaStatsContainer.addView(statView);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
|
|
||||||
<solid android:color="@color/primary" /> <!-- Fondo oscuro -->
|
<solid android:color="@color/textPrimary" /> <!-- Fondo oscuro -->
|
||||||
|
|
||||||
<corners android:radius="12dp" /> <!-- Bordes redondeados -->
|
<corners android:radius="12dp" /> <!-- Bordes redondeados -->
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 448 B |
Binary file not shown.
|
Before Width: | Height: | Size: 169 B |
Binary file not shown.
|
Before Width: | Height: | Size: 164 B |
|
|
@ -8,18 +8,17 @@
|
||||||
android:background="@color/background"
|
android:background="@color/background"
|
||||||
tools:context=".ui.MainActivity">
|
tools:context=".ui.MainActivity">
|
||||||
|
|
||||||
<!-- Contenedor para los fragments -->
|
<!-- Contenedor de fragments -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/frame_layout"
|
android:id="@+id/frame_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<!-- Toolbar personalizada -->
|
<!-- Toolbar superior -->
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="85dp"
|
android:layout_height="85dp"
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:background="@color/primary">
|
android:background="@color/primary">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
@ -28,7 +27,7 @@
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<!-- Logo (izquierda) -->
|
<!-- Logo -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/logoImage"
|
android:id="@+id/logoImage"
|
||||||
android:layout_width="100dp"
|
android:layout_width="100dp"
|
||||||
|
|
@ -38,7 +37,7 @@
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:src="@drawable/logo_yomitrack" />
|
android:src="@drawable/logo_yomitrack" />
|
||||||
|
|
||||||
<!-- Icono de perfil en la AppBar (circular) -->
|
<!-- Icono de perfil -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/profileIconToolbar"
|
android:id="@+id/profileIconToolbar"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
|
|
@ -53,7 +52,7 @@
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
<!-- BottomNavigationView (fuera del BottomAppBar) -->
|
<!-- Navegación inferior -->
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/bottomNavigationView"
|
android:id="@+id/bottomNavigationView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -1,224 +1,143 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@color/background"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
tools:context=".ui.fragments.anime_list.FragmentAnime">
|
||||||
|
|
||||||
<!-- Parte superior: imagen de fondo + avatar + nombre -->
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="match_parent">
|
||||||
android:background="@drawable/sample_cover"
|
|
||||||
android:padding="12dp">
|
|
||||||
|
|
||||||
<ImageView
|
<!-- Banner -->
|
||||||
android:id="@+id/imageViewBanner"
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/bannerLayout"
|
||||||
android:layout_height="match_parent"
|
android:layout_width="0dp"
|
||||||
android:scaleType="centerCrop"
|
android:layout_height="120dp"
|
||||||
android:src="@drawable/sample_cover"
|
android:background="@drawable/sample_cover"
|
||||||
android:contentDescription="Profile background" />
|
android:padding="12dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
<LinearLayout
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/imageViewBanner"
|
||||||
android:layout_height="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="horizontal"
|
android:layout_height="match_parent"
|
||||||
android:gravity="bottom"
|
android:scaleType="centerCrop"
|
||||||
android:paddingBottom="16dp">
|
android:src="@drawable/sample_cover"
|
||||||
|
android:contentDescription="Banner" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewAvatar"
|
android:id="@+id/imageViewAvatar"
|
||||||
android:layout_width="64dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="64dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginEnd="12dp"
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
android:src="@drawable/ic_profile"
|
android:src="@drawable/ic_profile"
|
||||||
android:background="@drawable/circle_mask"
|
android:background="@drawable/circle_mask"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:clipToOutline="true"
|
android:clipToOutline="true"
|
||||||
android:contentDescription="Profile picture" />
|
android:contentDescription="Avatar" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewUsername"
|
android:id="@+id/textViewUsername"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="BtwIsSanti"
|
android:layout_toEndOf="@id/imageViewAvatar"
|
||||||
|
android:layout_alignBottom="@id/imageViewAvatar"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:text="Usuario"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textSize="20sp"
|
android:textSize="18sp" />
|
||||||
android:gravity="center_vertical"/>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Búsqueda + botones -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/searchLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingBottom="4dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/bannerLayout"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editSearch"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/edit_text_background"
|
||||||
|
android:hint="Buscar anime..."
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:inputType="text" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnViewCompact"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:src="@drawable/ic_view_compact"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Vista Compacta" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnViewNormal"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:src="@drawable/ic_view_normal"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Vista Normal" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnViewLarge"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:src="@drawable/ic_view_large"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Vista Grande" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<!-- Tabs simulados -->
|
<!-- Lista de animes -->
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/recyclerViewAnime"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:background="@color/primary"
|
|
||||||
android:padding="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_height="0dp"
|
||||||
android:gravity="center"
|
|
||||||
android:text="Overview"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:layout_height="0dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Anime List"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_height="0dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Manga List"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:layout_height="0dp"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- Campo de búsqueda + botón de filtro + botones de vista -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingHorizontal="8dp"
|
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:weightSum="1">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/editTextFilter"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_weight="0.6"
|
|
||||||
android:hint="Filter"
|
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
|
||||||
android:background="@drawable/edittext_background"
|
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
android:textColor="@color/textPrimary"
|
android:paddingBottom="96dp"
|
||||||
android:inputType="text"
|
android:clipToPadding="false"
|
||||||
android:textSize="14sp" />
|
android:scrollbars="vertical"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/searchLayout"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<ImageView
|
<!-- FAB correctamente posicionado -->
|
||||||
android:id="@+id/buttonFilterMenu"
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:layout_width="0dp"
|
android:id="@+id/fabAddAnime"
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_weight="0.1"
|
|
||||||
android:src="@drawable/ic_more_vert"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="Filter menu"
|
|
||||||
android:padding="4dp"
|
|
||||||
app:tint="@color/textPrimary" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/buttonViewGrid"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_weight="0.1"
|
|
||||||
android:src="@drawable/ic_view_module"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="Grid view"
|
|
||||||
android:padding="4dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/buttonViewList"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_weight="0.1"
|
|
||||||
android:src="@drawable/ic_view_list"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="List view"
|
|
||||||
android:padding="4dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/buttonViewLarge"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_weight="0.1"
|
|
||||||
android:src="@drawable/ic_view_comfy"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="Large view"
|
|
||||||
android:padding="4dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Título del estado actual -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewWatching"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Watching"
|
android:layout_gravity="bottom|end"
|
||||||
android:textColor="@color/textPrimary"
|
android:layout_marginEnd="16dp"
|
||||||
android:textSize="16sp"
|
android:layout_marginBottom="40dp"
|
||||||
android:textStyle="bold"
|
android:contentDescription="Agregar anime"
|
||||||
android:layout_marginTop="4dp"
|
android:src="@drawable/ic_add"
|
||||||
android:layout_marginBottom="2dp" />
|
android:tint="@android:color/white"
|
||||||
|
app:backgroundTint="@color/primary" />
|
||||||
|
|
||||||
|
|
||||||
<!-- Encabezado tipo tabla -->
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:background="@color/primary">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="2"
|
|
||||||
android:text="Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="Score"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="Type"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="⋮"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="end"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- Lista de anime -->
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recyclerViewAnimeList"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:paddingBottom="8dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,69 @@
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
android:id="@+id/scrollView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
android:background="@color/background"
|
android:background="@color/background"
|
||||||
tools:context="ui.fragments.browse.FragmentBrowse">
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:text="Browse"
|
android:orientation="vertical">
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:textColor="@color/textPrimary"/>
|
|
||||||
|
|
||||||
</FrameLayout>
|
<!-- Espaciador reducido -->
|
||||||
|
<View
|
||||||
|
android:id="@+id/statusBarSpacer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="12dp" />
|
||||||
|
|
||||||
|
<!-- Encabezado -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textViewBrowse"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Browse"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/textPrimary"
|
||||||
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerType"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:backgroundTint="@color/primary" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Buscador -->
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editTextSearch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:hint="Search"
|
||||||
|
android:drawableStart="@android:drawable/ic_menu_search"
|
||||||
|
android:background="@drawable/edittext_background"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:textColor="@color/textPrimary"
|
||||||
|
android:textColorHint="@color/textPrimary" />
|
||||||
|
|
||||||
|
<!-- Contenedor de secciones -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sectionContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
|
||||||
|
|
@ -1,186 +1,111 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@color/background"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
tools:context=".ui.fragments.manga_list.FragmentManga">
|
tools:context=".ui.fragments.manga_list.FragmentManga">
|
||||||
|
|
||||||
<!-- Cabecera de usuario (opcional) -->
|
<LinearLayout
|
||||||
<RelativeLayout
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="match_parent">
|
||||||
android:background="@drawable/sample_cover"
|
|
||||||
android:padding="12dp">
|
|
||||||
|
|
||||||
<ImageView
|
<!-- Banner superior reducido -->
|
||||||
android:id="@+id/imageViewBanner"
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="120dp"
|
||||||
android:scaleType="centerCrop"
|
android:background="@drawable/sample_cover"
|
||||||
android:src="@drawable/sample_cover"
|
android:padding="12dp">
|
||||||
android:contentDescription="Profile background" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="bottom"
|
|
||||||
android:paddingBottom="16dp">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewAvatar"
|
android:id="@+id/imageViewBanner"
|
||||||
android:layout_width="64dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:src="@drawable/ic_profile"
|
|
||||||
android:background="@drawable/circle_mask"
|
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:clipToOutline="true"
|
android:src="@drawable/sample_cover"
|
||||||
android:contentDescription="Profile picture" />
|
android:contentDescription="Banner" />
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/textViewUsername"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:orientation="horizontal"
|
||||||
android:text="BtwIsSanti"
|
android:gravity="bottom|start"
|
||||||
android:textColor="@android:color/white"
|
android:paddingBottom="12dp"
|
||||||
android:textStyle="bold"
|
android:paddingStart="12dp"
|
||||||
android:textSize="20sp"
|
android:paddingEnd="12dp"
|
||||||
android:gravity="center_vertical"/>
|
android:layout_alignParentBottom="true">
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<!-- Filtros y modos de vista -->
|
<!-- Avatar -->
|
||||||
<LinearLayout
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/imageViewAvatar"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="48dp"
|
||||||
android:orientation="horizontal"
|
android:layout_height="48dp"
|
||||||
android:gravity="center_vertical"
|
android:src="@drawable/ic_profile"
|
||||||
android:paddingHorizontal="8dp"
|
android:background="@drawable/circle_mask"
|
||||||
android:paddingTop="4dp"
|
android:scaleType="centerCrop"
|
||||||
android:paddingBottom="4dp"
|
android:clipToOutline="true"
|
||||||
android:weightSum="1">
|
android:contentDescription="Avatar"
|
||||||
|
android:layout_marginEnd="12dp" />
|
||||||
|
|
||||||
<EditText
|
<!-- Nombre -->
|
||||||
android:id="@+id/editTextFilter"
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textViewUsername"
|
||||||
android:layout_height="40dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="0.6"
|
android:layout_height="wrap_content"
|
||||||
android:hint="Filter"
|
android:layout_weight="1"
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
android:text="Usuario"
|
||||||
android:background="@drawable/edittext_background"
|
android:textColor="@android:color/white"
|
||||||
android:padding="8dp"
|
android:textStyle="bold"
|
||||||
android:textColor="@color/textPrimary"
|
android:textSize="18sp"
|
||||||
android:inputType="text"
|
android:gravity="center_vertical" />
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<ImageView
|
<!-- Botón de cambiar vista -->
|
||||||
android:id="@+id/buttonFilterMenu"
|
<ImageButton
|
||||||
android:layout_width="0dp"
|
android:id="@+id/btnViewCompact"
|
||||||
android:layout_height="40dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="0.1"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_more_vert"
|
android:src="@drawable/ic_view_compact" />
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="Filter menu"
|
|
||||||
android:padding="4dp"
|
|
||||||
app:tint="@color/textPrimary" />
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/buttonViewGrid"
|
android:id="@+id/btnViewNormal"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="40dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0.1"
|
android:src="@drawable/ic_view_normal" />
|
||||||
android:src="@drawable/ic_view_module"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="Grid view"
|
|
||||||
android:padding="4dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/buttonViewList"
|
android:id="@+id/btnViewLarge"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="40dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0.1"
|
android:src="@drawable/ic_view_large" />
|
||||||
android:src="@drawable/ic_view_list"
|
</LinearLayout>
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
</RelativeLayout>
|
||||||
android:contentDescription="List view"
|
|
||||||
android:padding="4dp" />
|
|
||||||
|
|
||||||
<ImageButton
|
<!-- Lista scrollable -->
|
||||||
android:id="@+id/buttonViewLarge"
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/recyclerViewManga"
|
||||||
android:layout_height="40dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_weight="0.1"
|
android:layout_height="0dp"
|
||||||
android:src="@drawable/ic_view_comfy"
|
android:layout_weight="1"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:paddingStart="8dp"
|
||||||
android:contentDescription="Large view"
|
android:paddingEnd="8dp"
|
||||||
android:padding="4dp" />
|
android:paddingBottom="100dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:scrollbars="vertical" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Estado actual -->
|
<!-- FAB flotante -->
|
||||||
<TextView
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/textViewWatching"
|
android:id="@+id/fabAddManga"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Reading"
|
android:layout_gravity="bottom|end"
|
||||||
android:textColor="@color/textPrimary"
|
android:layout_margin="24dp"
|
||||||
android:textSize="16sp"
|
android:contentDescription="Agregar manga"
|
||||||
android:textStyle="bold"
|
android:src="@drawable/ic_add"
|
||||||
android:layout_marginTop="4dp"
|
android:tint="@android:color/white"
|
||||||
android:layout_marginBottom="2dp" />
|
app:backgroundTint="@color/primary" />
|
||||||
|
|
||||||
<!-- Encabezado tabla -->
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:background="@color/primary">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="2"
|
|
||||||
android:text="Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="Score"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="Type"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="⋮"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="end"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!-- Lista -->
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recyclerViewAnimeList"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:paddingBottom="8dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,58 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="8dp"
|
android:padding="12dp">
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewCover"
|
android:id="@+id/imageCover"
|
||||||
android:layout_width="40dp"
|
android:layout_width="72dp"
|
||||||
android:layout_height="55dp"
|
android:layout_height="96dp"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/sample_anime_cover"
|
android:layout_marginEnd="12dp"
|
||||||
android:background="@drawable/rounded_mask"
|
android:contentDescription="Portada" />
|
||||||
android:clipToOutline="true" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="2"
|
android:layout_weight="1">
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewTitle"
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Anime Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewProgress"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="5 / 12"
|
android:text="Título"
|
||||||
android:textColor="@color/textPrimary"
|
android:textStyle="bold"
|
||||||
android:textSize="12sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Estado"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="@android:color/darker_gray" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textScore"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Score: 80"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Progreso: 10 eps"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textType"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Tipo: TV"
|
||||||
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewScore"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="8.5"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewType"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="TV"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/buttonOptions"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:src="@drawable/ic_more_vert"
|
|
||||||
android:contentDescription="Options"
|
|
||||||
app:tint="@color/textPrimary" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,22 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="8dp">
|
android:padding="12dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewTitle"
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Anime Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewProgress"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Progress: 5 / 12"
|
android:text="Título Compacto"
|
||||||
android:textColor="@color/textPrimary"
|
android:textStyle="bold"
|
||||||
android:textSize="12sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Estado"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@android:color/darker_gray" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,51 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:layout_width="180dp"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp">
|
android:layout_margin="8dp">
|
||||||
|
|
||||||
|
<!-- Imagen de fondo -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewCover"
|
android:id="@+id/imageCover"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="240dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:background="@drawable/rounded_mask"
|
android:background="@drawable/rectangle_placeholder"
|
||||||
android:clipToOutline="true"
|
android:contentDescription="Portada" />
|
||||||
android:src="@drawable/sample_anime_cover" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<!-- Progreso en esquina inferior izquierda -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|start"
|
||||||
|
android:layout_margin="6dp"
|
||||||
|
android:text="6/12"
|
||||||
|
android:textColor="#FF4444"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
<!-- Título con fondo oscuro -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:padding="8dp"
|
android:background="#99000000"
|
||||||
android:orientation="horizontal"
|
android:text="Nombre del Anime"
|
||||||
android:gravity="center_vertical"
|
android:textColor="@android:color/white"
|
||||||
android:weightSum="1"
|
android:textSize="14sp"
|
||||||
android:background="#AA000000">
|
android:padding="6dp"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<!-- Indicador de estado (ej: Watching) -->
|
||||||
android:id="@+id/textViewProgress"
|
<View
|
||||||
android:layout_width="0dp"
|
android:id="@+id/statusDot"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="10dp"
|
||||||
android:layout_weight="0.5"
|
android:layout_height="10dp"
|
||||||
android:text="5 / 12"
|
android:layout_gravity="top|start"
|
||||||
android:textColor="@android:color/white"
|
android:layout_margin="6dp"
|
||||||
android:textSize="14sp"
|
android:background="@drawable/dot_green"
|
||||||
android:textStyle="bold" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewScore"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.5"
|
|
||||||
android:text="8.5"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:gravity="end" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,58 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="8dp"
|
android:padding="12dp">
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewCover"
|
android:id="@+id/imageCover"
|
||||||
android:layout_width="40dp"
|
android:layout_width="72dp"
|
||||||
android:layout_height="55dp"
|
android:layout_height="96dp"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/sample_anime_cover"
|
android:layout_marginEnd="12dp"
|
||||||
android:background="@drawable/rounded_mask"
|
android:contentDescription="Portada" />
|
||||||
android:clipToOutline="true" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="2"
|
android:layout_weight="1">
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewTitle"
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Manga Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewProgress"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="45 / 100"
|
android:text="Título"
|
||||||
android:textColor="@color/textPrimary"
|
android:textStyle="bold"
|
||||||
android:textSize="12sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Estado"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="@android:color/darker_gray" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textScore"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Score: 90"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Capítulos: 12"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textType"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Tipo: Manga"
|
||||||
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewScore"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="8.5"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewType"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.8"
|
|
||||||
android:text="Manga"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/buttonOptions"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:src="@drawable/ic_more_vert"
|
|
||||||
android:contentDescription="Options"
|
|
||||||
app:tint="@color/textPrimary" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,22 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="8dp">
|
android:padding="12dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textViewTitle"
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Manga Title"
|
|
||||||
android:textColor="@color/textPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:ellipsize="end" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewProgress"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Progress: 45 / 100"
|
android:text="Título Compacto"
|
||||||
android:textColor="@color/textPrimary"
|
android:textStyle="bold"
|
||||||
android:textSize="12sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Estado"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@android:color/darker_gray" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,51 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:layout_width="180dp"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="8dp">
|
android:layout_margin="8dp">
|
||||||
|
|
||||||
|
<!-- Imagen de fondo -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageViewCover"
|
android:id="@+id/imageCover"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="240dp"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:background="@drawable/rounded_mask"
|
android:background="@drawable/rectangle_placeholder"
|
||||||
android:clipToOutline="true"
|
android:contentDescription="Portada" />
|
||||||
android:src="@drawable/sample_anime_cover" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<!-- Progreso en esquina inferior izquierda -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|start"
|
||||||
|
android:layout_margin="6dp"
|
||||||
|
android:text="6/12"
|
||||||
|
android:textColor="#FF4444"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
<!-- Título con fondo oscuro -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:padding="8dp"
|
android:background="#99000000"
|
||||||
android:orientation="horizontal"
|
android:text="Nombre del Manga"
|
||||||
android:gravity="center_vertical"
|
android:textColor="@android:color/white"
|
||||||
android:weightSum="1"
|
android:textSize="14sp"
|
||||||
android:background="#AA000000">
|
android:padding="6dp"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<!-- Indicador de estado (ej: Watching) -->
|
||||||
android:id="@+id/textViewProgress"
|
<View
|
||||||
android:layout_width="0dp"
|
android:id="@+id/statusDot"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="10dp"
|
||||||
android:layout_weight="0.5"
|
android:layout_height="10dp"
|
||||||
android:text="45 / 100"
|
android:layout_gravity="top|start"
|
||||||
android:textColor="@android:color/white"
|
android:layout_margin="6dp"
|
||||||
android:textSize="14sp"
|
android:background="@drawable/dot_green"
|
||||||
android:textStyle="bold" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewScore"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="0.5"
|
|
||||||
android:text="8.5"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:gravity="end" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@
|
||||||
<color name="gray">#808080</color>
|
<color name="gray">#808080</color>
|
||||||
<color name="activeTint">#F26D50</color> <!-- estilo AniList -->
|
<color name="activeTint">#F26D50</color> <!-- estilo AniList -->
|
||||||
|
|
||||||
<!-- Colores por estado -->
|
<!-- Colores por estado anime -->
|
||||||
<color name="statWatching">#3db4f2</color>
|
<color name="status_completed">#4CAF50</color> <!-- verde -->
|
||||||
<color name="statCompleted">#16c98d</color>
|
<color name="status_watching">#2196F3</color> <!-- azul -->
|
||||||
<color name="statOnHold">#f5a623</color>
|
<color name="status_paused">#FFC107</color> <!-- amarillo -->
|
||||||
<color name="statDropped">#f45b69</color>
|
<color name="status_dropped">#F44336</color> <!-- rojo -->
|
||||||
<color name="statPlanToWatch">#c678dd</color>
|
<color name="status_planning">#9E9E9E</color> <!-- gris -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -20,4 +20,35 @@
|
||||||
<item name="imageViewCover" type="id" />
|
<item name="imageViewCover" type="id" />
|
||||||
<item name="textViewProgress" type="id" />
|
<item name="textViewProgress" type="id" />
|
||||||
<item name="textViewTitle" type="id" />
|
<item name="textViewTitle" type="id" />
|
||||||
|
<item name="buttonFilter" type="id" />
|
||||||
|
<item name="recyclerViewBrowse" type="id" />
|
||||||
|
<item name="spinnerType" type="id" />
|
||||||
|
<item name="textViewBrowse" type="id" />
|
||||||
|
<item name="editTextSearch" type="id" />
|
||||||
|
<item name="sectionContainer" type="id" />
|
||||||
|
<item name="statusBarSpacer" type="id" />
|
||||||
|
<item name="editTextPasswordRegister" type="id" />
|
||||||
|
<item name="buttonRegister" type="id" />
|
||||||
|
<item name="buttonAddItem" type="id" />
|
||||||
|
<item name="editTextPassword" type="id" />
|
||||||
|
<item name="buttonLogin" type="id" />
|
||||||
|
<item name="buttonGuest" type="id" />
|
||||||
|
<item name="buttonGoRegister" type="id" />
|
||||||
|
<item name="editTextUsername" type="id" />
|
||||||
|
<item name="fabAddAnime" type="id" />
|
||||||
|
<item name="recyclerViewAnime" type="id" />
|
||||||
|
<item name="fabAddManga" type="id" />
|
||||||
|
<item name="recyclerViewManga" type="id" />
|
||||||
|
<item name="imageViewBanner" type="id" />
|
||||||
|
<item name="imageViewAvatar" type="id" />
|
||||||
|
<item name="textViewUsername" type="id" />
|
||||||
|
<item name="buttonChangeViewType" type="id" />
|
||||||
|
<item name="recyclerSearchResults" type="id" />
|
||||||
|
<item name="buttonAddAnime" type="id" />
|
||||||
|
<item name="spinnerStatus" type="id" />
|
||||||
|
<item name="editTextAnimeTitle" type="id" />
|
||||||
|
<item name="spinnerEditStatus" type="id" />
|
||||||
|
<item name="buttonSaveAnime" type="id" />
|
||||||
|
<item name="statusDot" type="id" />
|
||||||
|
<item name="editSearch" type="id" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -7,4 +7,39 @@
|
||||||
<string name="profile">\n</string>
|
<string name="profile">\n</string>
|
||||||
<string name="write_a_status">Write a status...</string>
|
<string name="write_a_status">Write a status...</string>
|
||||||
<string name="show_more" />
|
<string name="show_more" />
|
||||||
|
<string-array name="media_types">
|
||||||
|
<item>Anime</item>
|
||||||
|
<item>Manga</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="anime_status_array">
|
||||||
|
<item>Watching</item>
|
||||||
|
<item>Completed</item>
|
||||||
|
<item>Paused</item>
|
||||||
|
<item>Dropped</item>
|
||||||
|
<item>Planning</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="anime_type_array">
|
||||||
|
<item>TV</item>
|
||||||
|
<item>Movie</item>
|
||||||
|
<item>OVA</item>
|
||||||
|
<item>ONA</item>
|
||||||
|
<item>Special</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="manga_status_array">
|
||||||
|
<item>Reading</item>
|
||||||
|
<item>Completed</item>
|
||||||
|
<item>Paused</item>
|
||||||
|
<item>Dropped</item>
|
||||||
|
<item>Planning</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="manga_type_array">
|
||||||
|
<item>Manga</item>
|
||||||
|
<item>Manhwa</item>
|
||||||
|
<item>Manhua</item>
|
||||||
|
<item>Novel</item>
|
||||||
|
<item>One-shot</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[versions]
|
[versions]
|
||||||
agp = "8.9.2"
|
agp = "8.10.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.2.1"
|
junitVersion = "1.2.1"
|
||||||
espressoCore = "3.6.1"
|
espressoCore = "3.6.1"
|
||||||
|
|
@ -7,6 +7,8 @@ appcompat = "1.7.0"
|
||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
activity = "1.10.1"
|
activity = "1.10.1"
|
||||||
constraintlayout = "2.2.1"
|
constraintlayout = "2.2.1"
|
||||||
|
navigationFragment = "2.9.0"
|
||||||
|
navigationUi = "2.9.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
|
|
@ -16,6 +18,8 @@ appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "a
|
||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
|
navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment", version.ref = "navigationFragment" }
|
||||||
|
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue