erro
This commit is contained in:
@@ -32,8 +32,7 @@
|
||||
<activity android:name=".FindFriendsActivity" />
|
||||
<activity android:name=".TrophiesActivity" />
|
||||
<activity android:name=".MyFriendsActivity" />
|
||||
|
||||
|
||||
<activity android:name=".AvatarEditorActivity" />
|
||||
|
||||
</application>
|
||||
|
||||
|
||||
26
app/src/main/java/com/fluxup/app/AvatarData.java
Normal file
26
app/src/main/java/com/fluxup/app/AvatarData.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.fluxup.app;
|
||||
|
||||
public class AvatarData {
|
||||
public String skinColor = "#FFD1B3";
|
||||
public String bodyFormat = "slim"; // slim, athletic, plus
|
||||
public int heightOffset = 0; // -10, 0, 10
|
||||
|
||||
public String hairStyle = "short"; // short, spiky, long, bald, fade, curly
|
||||
public String hairColor = "#4A4A4A";
|
||||
|
||||
public String eyesStyle = "normal"; // normal, happy, cool, cute
|
||||
public String eyebrowsStyle = "normal"; // normal, thick, angry, sad
|
||||
public String mouthStyle = "smile"; // smile, smirk, open, neutral
|
||||
|
||||
public String clothesStyle = "tshirt"; // tshirt, hoodie, outfit, sport
|
||||
public String clothesColor = "#7C3AED";
|
||||
|
||||
public String beardStyle = "none"; // none, goatee, full
|
||||
public String accessory = "none"; // none, glasses, headphones, chain, cap
|
||||
|
||||
// Novas propriedades de cosméticos desbloqueáveis
|
||||
public String effect = "none"; // none, fire_aura, glow
|
||||
public String frame = "none"; // none, gold, neon
|
||||
|
||||
public AvatarData() {}
|
||||
}
|
||||
253
app/src/main/java/com/fluxup/app/AvatarEditorActivity.java
Normal file
253
app/src/main/java/com/fluxup/app/AvatarEditorActivity.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package com.fluxup.app;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.firestore.FirebaseFirestore;
|
||||
|
||||
public class AvatarEditorActivity extends AppCompatActivity {
|
||||
|
||||
private AvatarView previewAvatar;
|
||||
private AvatarData currentData;
|
||||
private Usuario currentUser;
|
||||
|
||||
// Novas listas expandidas com suporte a progressão
|
||||
private String[] skinColors = {"#FFD1B3", "#FFDBAC", "#F1C27D", "#E0AC69", "#C68642", "#8D5524", "#3E2723"};
|
||||
private String[] bodyFormats = {"slim", "athletic", "plus"};
|
||||
private String[] hairStyles = {"short", "spiky", "long", "bald", "fade", "curly"};
|
||||
private String[] hairColors = {"#4A4A4A", "#1A1A1A", "#C68642", "#E8B253", "#EF4444", "#3B82F6", "#10B981"};
|
||||
private String[] eyeStyles = {"normal", "happy", "cool", "cute"};
|
||||
private String[] eyebrowStyles = {"normal", "thick", "angry", "sad"};
|
||||
private String[] mouthStyles = {"smile", "smirk", "open", "neutral"};
|
||||
private String[] clothesStyles = {"tshirt", "hoodie", "outfit", "sport"};
|
||||
private String[] clothesColors = {"#7C3AED", "#EF4444", "#3B82F6", "#10B981", "#F59E0B", "#1E293B", "#F8FAFC"};
|
||||
private String[] beardStyles = {"none", "goatee", "full"};
|
||||
private String[] accessories = {"none", "glasses", "headphones", "chain", "cap"};
|
||||
private String[] frames = {"none", "gold", "neon"};
|
||||
private String[] effects = {"none", "fire_aura", "glow"};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_avatar_editor);
|
||||
|
||||
previewAvatar = findViewById(R.id.previewAvatar);
|
||||
|
||||
findViewById(R.id.btnBackEditor).setOnClickListener(v -> finish());
|
||||
findViewById(R.id.btnSaveTop).setOnClickListener(v -> saveAvatar());
|
||||
|
||||
setupTabs();
|
||||
loadCurrentAvatar();
|
||||
}
|
||||
|
||||
private void loadCurrentAvatar() {
|
||||
FirebaseUser fUser = AuthManager.getInstance().getCurrentUser();
|
||||
if (fUser != null) {
|
||||
FirestoreManager.getInstance().getUser(fUser.getUid(), user -> {
|
||||
if (user != null) {
|
||||
this.currentUser = user;
|
||||
this.currentData = user.avatar != null ? user.avatar : new AvatarData();
|
||||
previewAvatar.setAvatarData(this.currentData);
|
||||
populateAllOptions();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setupTabs() {
|
||||
com.google.android.material.tabs.TabLayout tabs = findViewById(R.id.tabsCategories);
|
||||
tabs.addOnTabSelectedListener(new com.google.android.material.tabs.TabLayout.OnTabSelectedListener() {
|
||||
@Override public void onTabSelected(com.google.android.material.tabs.TabLayout.Tab tab) {
|
||||
findViewById(R.id.panelCorpo).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelCabelo).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelRosto).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelRoupa).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelAcessorios).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelMolduras).setVisibility(android.view.View.GONE);
|
||||
findViewById(R.id.panelEfeitos).setVisibility(android.view.View.GONE);
|
||||
|
||||
int pos = tab.getPosition();
|
||||
if (pos == 0) findViewById(R.id.panelCorpo).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 1) findViewById(R.id.panelCabelo).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 2) findViewById(R.id.panelRosto).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 3) findViewById(R.id.panelRoupa).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 4) findViewById(R.id.panelAcessorios).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 5) findViewById(R.id.panelMolduras).setVisibility(android.view.View.VISIBLE);
|
||||
else if (pos == 6) findViewById(R.id.panelEfeitos).setVisibility(android.view.View.VISIBLE);
|
||||
}
|
||||
@Override public void onTabUnselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
|
||||
@Override public void onTabReselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void populateAllOptions() {
|
||||
populateColorList(R.id.llSkinColors, skinColors, "skinColor");
|
||||
populateTextList(R.id.llBodyFormats, bodyFormats, "bodyFormat");
|
||||
|
||||
populateTextList(R.id.llHairStyles, hairStyles, "hairStyle");
|
||||
populateColorList(R.id.llHairColors, hairColors, "hairColor");
|
||||
|
||||
populateTextList(R.id.llEyes, eyeStyles, "eyesStyle");
|
||||
populateTextList(R.id.llEyebrows, eyebrowStyles, "eyebrowsStyle");
|
||||
populateTextList(R.id.llMouth, mouthStyles, "mouthStyle");
|
||||
populateTextList(R.id.llBeard, beardStyles, "beardStyle");
|
||||
|
||||
populateTextList(R.id.llClothes, clothesStyles, "clothesStyle");
|
||||
populateColorList(R.id.llClothesColors, clothesColors, "clothesColor");
|
||||
|
||||
populateTextList(R.id.llAccessories, accessories, "accessory");
|
||||
|
||||
populateTextList(R.id.llFrames, frames, "frame");
|
||||
populateTextList(R.id.llEffects, effects, "effect");
|
||||
}
|
||||
|
||||
private void populateColorList(int containerId, String[] colors, String property) {
|
||||
android.widget.LinearLayout container = findViewById(containerId);
|
||||
container.removeAllViews();
|
||||
|
||||
for (String color : colors) {
|
||||
androidx.cardview.widget.CardView card = new androidx.cardview.widget.CardView(this);
|
||||
android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(120, 120);
|
||||
params.setMargins(0, 0, 24, 0);
|
||||
card.setLayoutParams(params);
|
||||
card.setRadius(60f);
|
||||
card.setCardElevation(4f);
|
||||
card.setCardBackgroundColor(android.graphics.Color.parseColor(color));
|
||||
|
||||
// Checkmark no selecionado
|
||||
String currentValue = getCurrentPropertyValue(property);
|
||||
if (color.equalsIgnoreCase(currentValue)) {
|
||||
android.widget.TextView check = new android.widget.TextView(this);
|
||||
check.setText("✓");
|
||||
check.setTextColor(android.graphics.Color.WHITE);
|
||||
check.setGravity(android.view.Gravity.CENTER);
|
||||
check.setTextSize(16f);
|
||||
check.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||
card.addView(check);
|
||||
}
|
||||
|
||||
card.setOnClickListener(v -> {
|
||||
updateProperty(property, color);
|
||||
populateAllOptions();
|
||||
});
|
||||
container.addView(card);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateTextList(int containerId, String[] options, String property) {
|
||||
android.widget.LinearLayout container = findViewById(containerId);
|
||||
container.removeAllViews();
|
||||
|
||||
for (String opt : options) {
|
||||
android.widget.TextView tv = new android.widget.TextView(this);
|
||||
android.widget.LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(
|
||||
android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, 120);
|
||||
params.setMargins(0, 0, 24, 0);
|
||||
tv.setLayoutParams(params);
|
||||
|
||||
boolean isLocked = UnlockManager.isItemLockedForUser(currentUser, property, opt);
|
||||
CosmeticItem lockInfo = UnlockManager.findCosmetic(property, opt);
|
||||
|
||||
if (isLocked && lockInfo != null) {
|
||||
tv.setText("🔒 " + opt.toUpperCase());
|
||||
tv.setGravity(android.view.Gravity.CENTER);
|
||||
tv.setPadding(40, 0, 40, 0);
|
||||
tv.setTextColor(android.graphics.Color.parseColor("#94A3B8"));
|
||||
tv.setTextSize(12f);
|
||||
tv.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||
|
||||
android.graphics.drawable.GradientDrawable gd = new android.graphics.drawable.GradientDrawable();
|
||||
gd.setColor(android.graphics.Color.parseColor("#E2E8F0"));
|
||||
gd.setCornerRadius(60f);
|
||||
gd.setStroke(2, android.graphics.Color.parseColor("#CBD5E1"));
|
||||
tv.setBackground(gd);
|
||||
|
||||
tv.setOnClickListener(v -> {
|
||||
Toast.makeText(this, lockInfo.unlockRequirement, Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
} else {
|
||||
tv.setText(opt.toUpperCase());
|
||||
tv.setGravity(android.view.Gravity.CENTER);
|
||||
tv.setPadding(40, 0, 40, 0);
|
||||
tv.setTextColor(android.graphics.Color.parseColor("#333333"));
|
||||
tv.setTextSize(12f);
|
||||
tv.setTypeface(null, android.graphics.Typeface.BOLD);
|
||||
|
||||
android.graphics.drawable.GradientDrawable gd = new android.graphics.drawable.GradientDrawable();
|
||||
String currentValue = getCurrentPropertyValue(property);
|
||||
if (opt.equals(currentValue)) {
|
||||
gd.setColor(android.graphics.Color.parseColor("#7C3AED"));
|
||||
tv.setTextColor(android.graphics.Color.WHITE);
|
||||
} else {
|
||||
gd.setColor(android.graphics.Color.parseColor("#E2E8F0"));
|
||||
}
|
||||
gd.setCornerRadius(60f);
|
||||
tv.setBackground(gd);
|
||||
|
||||
tv.setOnClickListener(v -> {
|
||||
updateProperty(property, opt);
|
||||
populateAllOptions();
|
||||
});
|
||||
}
|
||||
container.addView(tv);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCurrentPropertyValue(String property) {
|
||||
if (currentData == null) return "";
|
||||
switch (property) {
|
||||
case "skinColor": return currentData.skinColor;
|
||||
case "bodyFormat": return currentData.bodyFormat;
|
||||
case "hairStyle": return currentData.hairStyle;
|
||||
case "hairColor": return currentData.hairColor;
|
||||
case "eyesStyle": return currentData.eyesStyle;
|
||||
case "eyebrowsStyle": return currentData.eyebrowsStyle;
|
||||
case "mouthStyle": return currentData.mouthStyle;
|
||||
case "clothesStyle": return currentData.clothesStyle;
|
||||
case "clothesColor": return currentData.clothesColor;
|
||||
case "beardStyle": return currentData.beardStyle;
|
||||
case "accessory": return currentData.accessory;
|
||||
case "frame": return currentData.frame;
|
||||
case "effect": return currentData.effect;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateProperty(String property, String value) {
|
||||
if (currentData == null) return;
|
||||
switch (property) {
|
||||
case "skinColor": currentData.skinColor = value; break;
|
||||
case "bodyFormat": currentData.bodyFormat = value; break;
|
||||
case "hairStyle": currentData.hairStyle = value; break;
|
||||
case "hairColor": currentData.hairColor = value; break;
|
||||
case "eyesStyle": currentData.eyesStyle = value; break;
|
||||
case "eyebrowsStyle": currentData.eyebrowsStyle = value; break;
|
||||
case "mouthStyle": currentData.mouthStyle = value; break;
|
||||
case "clothesStyle": currentData.clothesStyle = value; break;
|
||||
case "clothesColor": currentData.clothesColor = value; break;
|
||||
case "beardStyle": currentData.beardStyle = value; break;
|
||||
case "accessory": currentData.accessory = value; break;
|
||||
case "frame": currentData.frame = value; break;
|
||||
case "effect": currentData.effect = value; break;
|
||||
}
|
||||
previewAvatar.setAvatarData(currentData);
|
||||
}
|
||||
|
||||
private void saveAvatar() {
|
||||
if (currentUser == null) return;
|
||||
currentUser.avatar = currentData;
|
||||
FirebaseFirestore.getInstance().collection("users").document(currentUser.id_usuario)
|
||||
.update("avatar", currentData)
|
||||
.addOnSuccessListener(aVoid -> {
|
||||
Toast.makeText(this, "Avatar atualizado com sucesso!", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
})
|
||||
.addOnFailureListener(e -> {
|
||||
Toast.makeText(this, "Erro ao guardar", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
}
|
||||
370
app/src/main/java/com/fluxup/app/AvatarView.java
Normal file
370
app/src/main/java/com/fluxup/app/AvatarView.java
Normal file
@@ -0,0 +1,370 @@
|
||||
package com.fluxup.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class AvatarView extends View {
|
||||
|
||||
private AvatarData avatarData = new AvatarData();
|
||||
private Paint paint;
|
||||
private Path path;
|
||||
|
||||
public AvatarView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public AvatarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
path = new Path();
|
||||
}
|
||||
|
||||
private String league = "Bronze";
|
||||
|
||||
public void setAvatarData(AvatarData data) {
|
||||
if (data != null) {
|
||||
this.avatarData = data;
|
||||
invalidate(); // Redraw
|
||||
}
|
||||
}
|
||||
|
||||
public void setLeague(String league) {
|
||||
if (league != null) {
|
||||
this.league = league;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private int parseSafeColor(String colorStr, String defaultHex) {
|
||||
try {
|
||||
if (colorStr == null || colorStr.isEmpty()) return Color.parseColor(defaultHex);
|
||||
return Color.parseColor(colorStr);
|
||||
} catch (Exception e) {
|
||||
return Color.parseColor(defaultHex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
int w = getWidth();
|
||||
int h = getHeight();
|
||||
if (w == 0 || h == 0) return;
|
||||
|
||||
// Fundo circular premium
|
||||
paint.setColor(Color.parseColor("#F8FAFC"));
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setAntiAlias(true);
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f, paint);
|
||||
|
||||
canvas.save();
|
||||
float scale = Math.min(w / 100f, h / 100f);
|
||||
canvas.translate((w - 100f * scale) / 2f, (h - 100f * scale) / 2f);
|
||||
canvas.scale(scale, scale);
|
||||
|
||||
// Translacao da altura
|
||||
canvas.translate(0, avatarData.heightOffset);
|
||||
|
||||
// --- EFEITOS (Desenhados atrás do avatar) ---
|
||||
if ("fire_aura".equals(avatarData.effect)) {
|
||||
paint.setColor(Color.parseColor("#F97316")); // Laranja fogo
|
||||
canvas.drawCircle(25, 75, 18, paint);
|
||||
canvas.drawCircle(75, 75, 18, paint);
|
||||
paint.setColor(Color.parseColor("#F59E0B")); // Amarelo fogo
|
||||
canvas.drawCircle(35, 80, 12, paint);
|
||||
canvas.drawCircle(65, 80, 12, paint);
|
||||
canvas.drawCircle(50, 85, 14, paint);
|
||||
} else if ("glow".equals(avatarData.effect)) {
|
||||
paint.setColor(Color.parseColor("#E9D5FF")); // Roxo suave brilhante
|
||||
canvas.drawCircle(50, 50, 42, paint);
|
||||
paint.setColor(Color.parseColor("#F5F3FF")); // Fundo interior leve
|
||||
canvas.drawCircle(50, 50, 36, paint);
|
||||
}
|
||||
|
||||
// Cores
|
||||
int skinCol = parseSafeColor(avatarData.skinColor, "#FFD1B3");
|
||||
int clothesCol = parseSafeColor(avatarData.clothesColor, "#7C3AED");
|
||||
int hairCol = parseSafeColor(avatarData.hairColor, "#4A4A4A");
|
||||
|
||||
// --- CORPO (Muito pequeno e simplificado) ---
|
||||
float bodyW = 40f;
|
||||
if ("athletic".equals(avatarData.bodyFormat)) bodyW = 48f;
|
||||
else if ("plus".equals(avatarData.bodyFormat)) bodyW = 56f;
|
||||
|
||||
float bodyLeft = 50f - (bodyW / 2f);
|
||||
float bodyRight = 50f + (bodyW / 2f);
|
||||
|
||||
// PESCOÇO
|
||||
paint.setColor(darkenColor(skinCol, 0.8f)); // Sombra do pescoço
|
||||
canvas.drawRoundRect(new RectF(43, 65, 57, 85), 6, 6, paint);
|
||||
|
||||
// ROUPA
|
||||
paint.setColor(clothesCol);
|
||||
paint.setShadowLayer(4f, 0f, 4f, Color.parseColor("#33000000")); // Sombra 3D
|
||||
|
||||
if ("hoodie".equals(avatarData.clothesStyle)) {
|
||||
// Capuz atrás
|
||||
canvas.drawRoundRect(new RectF(bodyLeft - 5, 72, bodyRight + 5, 110), 16, 16, paint);
|
||||
// Corpo
|
||||
canvas.drawRoundRect(new RectF(bodyLeft, 78, bodyRight, 110), 12, 12, paint);
|
||||
// Cordões
|
||||
paint.clearShadowLayer();
|
||||
paint.setColor(Color.WHITE);
|
||||
canvas.drawRoundRect(new RectF(45, 82, 47, 95), 1, 1, paint);
|
||||
canvas.drawRoundRect(new RectF(53, 82, 55, 95), 1, 1, paint);
|
||||
} else if ("sport".equals(avatarData.clothesStyle)) {
|
||||
canvas.drawRoundRect(new RectF(bodyLeft, 78, bodyRight, 110), 8, 8, paint);
|
||||
paint.clearShadowLayer();
|
||||
paint.setColor(Color.WHITE);
|
||||
canvas.drawRect(bodyLeft + 10, 78, bodyRight - 10, 110, paint);
|
||||
} else if ("outfit".equals(avatarData.clothesStyle)) {
|
||||
// Casaco aberto
|
||||
canvas.drawRoundRect(new RectF(bodyLeft - 2, 78, bodyRight + 2, 110), 10, 10, paint);
|
||||
paint.clearShadowLayer();
|
||||
paint.setColor(Color.WHITE); // T-shirt interior
|
||||
canvas.drawRect(42, 78, 58, 110, paint);
|
||||
} else { // tshirt
|
||||
canvas.drawRoundRect(new RectF(bodyLeft, 78, bodyRight, 110), 10, 10, paint);
|
||||
paint.clearShadowLayer();
|
||||
paint.setColor(skinCol);
|
||||
canvas.drawArc(new RectF(40, 72, 60, 84), 0, 180, false, paint);
|
||||
}
|
||||
paint.clearShadowLayer();
|
||||
|
||||
// --- CABEÇA (Grande e expressiva) ---
|
||||
paint.setColor(skinCol);
|
||||
paint.setShadowLayer(6f, 0f, 6f, Color.parseColor("#22000000"));
|
||||
|
||||
// Orelhas
|
||||
canvas.drawCircle(22, 45, 6, paint);
|
||||
canvas.drawCircle(78, 45, 6, paint);
|
||||
|
||||
// Formato principal da cabeça
|
||||
canvas.drawRoundRect(new RectF(20, 15, 80, 70), 28, 28, paint);
|
||||
paint.clearShadowLayer();
|
||||
|
||||
// --- CABELO Atrás / Base ---
|
||||
paint.setColor(hairCol);
|
||||
if ("long".equals(avatarData.hairStyle)) {
|
||||
canvas.drawRoundRect(new RectF(16, 30, 32, 85), 8, 8, paint);
|
||||
canvas.drawRoundRect(new RectF(68, 30, 84, 85), 8, 8, paint);
|
||||
} else if ("curly".equals(avatarData.hairStyle)) {
|
||||
canvas.drawCircle(18, 35, 12, paint);
|
||||
canvas.drawCircle(82, 35, 12, paint);
|
||||
}
|
||||
|
||||
// --- BARBA ---
|
||||
if (!"none".equals(avatarData.beardStyle)) {
|
||||
paint.setColor(darkenColor(hairCol, 0.9f));
|
||||
if ("goatee".equals(avatarData.beardStyle)) {
|
||||
canvas.drawRoundRect(new RectF(44, 58, 56, 68), 6, 6, paint);
|
||||
} else if ("full".equals(avatarData.beardStyle)) {
|
||||
canvas.drawRoundRect(new RectF(25, 45, 75, 70), 15, 15, paint);
|
||||
paint.setColor(skinCol);
|
||||
canvas.drawRoundRect(new RectF(35, 45, 65, 58), 10, 10, paint); // Área da boca limpa
|
||||
}
|
||||
}
|
||||
|
||||
// --- OLHOS ---
|
||||
paint.setColor(Color.parseColor("#1E293B"));
|
||||
if ("happy".equals(avatarData.eyesStyle)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(3f);
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
canvas.drawArc(new RectF(32, 40, 42, 48), 180, 180, false, paint);
|
||||
canvas.drawArc(new RectF(58, 40, 68, 48), 180, 180, false, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("cool".equals(avatarData.eyesStyle)) {
|
||||
canvas.drawRoundRect(new RectF(32, 42, 42, 46), 2, 2, paint);
|
||||
canvas.drawRoundRect(new RectF(58, 42, 68, 46), 2, 2, paint);
|
||||
} else if ("cute".equals(avatarData.eyesStyle)) {
|
||||
canvas.drawCircle(37, 44, 5, paint);
|
||||
canvas.drawCircle(63, 44, 5, paint);
|
||||
paint.setColor(Color.WHITE);
|
||||
canvas.drawCircle(38, 42, 1.5f, paint);
|
||||
canvas.drawCircle(64, 42, 1.5f, paint);
|
||||
} else { // normal
|
||||
canvas.drawCircle(37, 44, 4.5f, paint);
|
||||
canvas.drawCircle(63, 44, 4.5f, paint);
|
||||
}
|
||||
|
||||
// --- SOBRANCELHAS ---
|
||||
paint.setColor(darkenColor(hairCol, 0.8f));
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth("thick".equals(avatarData.eyebrowsStyle) ? 4f : 2.5f);
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
|
||||
if ("angry".equals(avatarData.eyebrowsStyle)) {
|
||||
canvas.drawLine(30, 32, 44, 38, paint);
|
||||
canvas.drawLine(70, 32, 56, 38, paint);
|
||||
} else if ("sad".equals(avatarData.eyebrowsStyle)) {
|
||||
canvas.drawLine(30, 38, 44, 32, paint);
|
||||
canvas.drawLine(70, 38, 56, 32, paint);
|
||||
} else { // normal / thick
|
||||
canvas.drawLine(32, 35, 42, 35, paint);
|
||||
canvas.drawLine(58, 35, 68, 35, paint);
|
||||
}
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
||||
// --- BOCA ---
|
||||
paint.setColor(Color.parseColor("#BE123C")); // Vermelho suave
|
||||
if ("smile".equals(avatarData.mouthStyle)) {
|
||||
canvas.drawArc(new RectF(42, 53, 58, 62), 0, 180, false, paint);
|
||||
} else if ("open".equals(avatarData.mouthStyle)) {
|
||||
canvas.drawRoundRect(new RectF(44, 55, 56, 62), 4, 4, paint);
|
||||
paint.setColor(Color.WHITE); // Dentes
|
||||
canvas.drawRect(45, 55, 55, 57, paint);
|
||||
} else if ("smirk".equals(avatarData.mouthStyle)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(2f);
|
||||
canvas.drawArc(new RectF(45, 54, 55, 60), 0, 130, false, paint);
|
||||
canvas.drawLine(54, 55, 57, 53, paint); // sorrisinho de lado
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else { // neutral
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(2.5f);
|
||||
canvas.drawLine(46, 57, 54, 57, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
}
|
||||
|
||||
// --- CABELO Topo / Franja ---
|
||||
paint.setColor(hairCol);
|
||||
if ("short".equals(avatarData.hairStyle) || "long".equals(avatarData.hairStyle)) {
|
||||
canvas.drawArc(new RectF(18, 8, 82, 40), 180, 180, false, paint);
|
||||
canvas.drawRoundRect(new RectF(18, 20, 30, 45), 4, 4, paint); // patilhas
|
||||
canvas.drawRoundRect(new RectF(70, 20, 82, 45), 4, 4, paint);
|
||||
} else if ("spiky".equals(avatarData.hairStyle)) {
|
||||
path.reset();
|
||||
path.moveTo(18, 30);
|
||||
path.lineTo(30, 5);
|
||||
path.lineTo(40, 15);
|
||||
path.lineTo(50, 0);
|
||||
path.lineTo(60, 15);
|
||||
path.lineTo(70, 5);
|
||||
path.lineTo(82, 30);
|
||||
path.close();
|
||||
canvas.drawPath(path, paint);
|
||||
} else if ("fade".equals(avatarData.hairStyle)) {
|
||||
canvas.drawRoundRect(new RectF(25, 5, 75, 25), 8, 8, paint);
|
||||
paint.setColor(darkenColor(skinCol, 0.9f));
|
||||
canvas.drawRoundRect(new RectF(18, 20, 25, 40), 2, 2, paint);
|
||||
canvas.drawRoundRect(new RectF(75, 20, 82, 40), 2, 2, paint);
|
||||
} else if ("curly".equals(avatarData.hairStyle)) {
|
||||
canvas.drawCircle(30, 15, 14, paint);
|
||||
canvas.drawCircle(50, 10, 16, paint);
|
||||
canvas.drawCircle(70, 15, 14, paint);
|
||||
canvas.drawCircle(22, 25, 12, paint);
|
||||
canvas.drawCircle(78, 25, 12, paint);
|
||||
}
|
||||
|
||||
// --- ACESSÓRIOS ---
|
||||
if ("glasses".equals(avatarData.accessory)) {
|
||||
paint.setColor(Color.parseColor("#1E293B"));
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(3f);
|
||||
canvas.drawRoundRect(new RectF(28, 38, 46, 50), 6, 6, paint);
|
||||
canvas.drawRoundRect(new RectF(54, 38, 72, 50), 6, 6, paint);
|
||||
canvas.drawLine(46, 44, 54, 44, paint); // ponte
|
||||
canvas.drawLine(20, 42, 28, 44, paint); // hastes
|
||||
canvas.drawLine(80, 42, 72, 44, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("headphones".equals(avatarData.accessory)) {
|
||||
paint.setColor(Color.parseColor("#334155"));
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(4f);
|
||||
canvas.drawArc(new RectF(18, 12, 82, 60), 180, 180, false, paint); // aro
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(Color.parseColor("#E2E8F0"));
|
||||
canvas.drawRoundRect(new RectF(12, 35, 22, 55), 4, 4, paint); // concha esq
|
||||
canvas.drawRoundRect(new RectF(78, 35, 88, 55), 4, 4, paint); // concha dir
|
||||
} else if ("chain".equals(avatarData.accessory)) {
|
||||
paint.setColor(Color.parseColor("#FBBF24")); // Dourado
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(2.5f);
|
||||
canvas.drawArc(new RectF(40, 72, 60, 88), 0, 180, false, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("cap".equals(avatarData.accessory)) {
|
||||
paint.setColor(Color.parseColor("#0F172A")); // Boné escuro
|
||||
canvas.drawArc(new RectF(18, 5, 82, 35), 180, 180, false, paint); // copa
|
||||
canvas.drawRoundRect(new RectF(15, 25, 90, 32), 4, 4, paint); // aba
|
||||
}
|
||||
|
||||
canvas.restore();
|
||||
|
||||
// --- MOLDURA (Desenhada no limite exterior do círculo) ---
|
||||
String activeFrame = avatarData.frame;
|
||||
if ("none".equals(activeFrame) || activeFrame == null) {
|
||||
// Desenhar molduras automáticas por Liga
|
||||
if ("Prata".equalsIgnoreCase(league) || "Silver".equalsIgnoreCase(league)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
|
||||
paint.setColor(Color.parseColor("#CBD5E1")); // Prata
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("Ouro".equalsIgnoreCase(league) || "Gold".equalsIgnoreCase(league)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
|
||||
paint.setColor(Color.parseColor("#F59E0B")); // Ouro
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("Platina".equalsIgnoreCase(league) || "Platinum".equalsIgnoreCase(league)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
|
||||
paint.setColor(Color.parseColor("#06B6D4")); // Platina Ciano
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("Diamante".equalsIgnoreCase(league) || "Diamond".equalsIgnoreCase(league)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.06f);
|
||||
paint.setColor(Color.parseColor("#6366F1")); // Diamante Indigo/Violeta
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
}
|
||||
} else {
|
||||
// Moldura manual equipada explícita
|
||||
if ("gold".equals(activeFrame)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.08f); // 8% da espessura
|
||||
paint.setColor(Color.parseColor("#FBBF24")); // Dourado
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
|
||||
// Linha interior metálica
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.02f);
|
||||
paint.setColor(Color.parseColor("#D97706")); // Dourado Escuro
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - Math.min(w, h)*0.07f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
} else if ("neon".equals(activeFrame)) {
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.08f);
|
||||
paint.setColor(Color.parseColor("#C084FC")); // Roxo Neon
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - paint.getStrokeWidth()/2f, paint);
|
||||
|
||||
// Linha interior ciano
|
||||
paint.setStrokeWidth(Math.min(w, h) * 0.02f);
|
||||
paint.setColor(Color.parseColor("#22D3EE")); // Ciano Neon
|
||||
canvas.drawCircle(w/2f, h/2f, Math.min(w, h)/2f - Math.min(w, h)*0.07f, paint);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int darkenColor(int color, float factor) {
|
||||
int a = Color.alpha(color);
|
||||
int r = Math.round(Color.red(color) * factor);
|
||||
int g = Math.round(Color.green(color) * factor);
|
||||
int b = Math.round(Color.blue(color) * factor);
|
||||
return Color.argb(a, Math.min(r, 255), Math.min(g, 255), Math.min(b, 255));
|
||||
}
|
||||
}
|
||||
40
app/src/main/java/com/fluxup/app/CosmeticItem.java
Normal file
40
app/src/main/java/com/fluxup/app/CosmeticItem.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.fluxup.app;
|
||||
|
||||
public class CosmeticItem {
|
||||
public String id;
|
||||
public String name;
|
||||
public String category; // "corpo", "cabelo", "rosto", "roupa", "acessorios", "efeitos", "molduras"
|
||||
public String property; // "clothesStyle", "accessory", "frame", "effect", etc.
|
||||
public String value;
|
||||
public String unlockRequirement;
|
||||
|
||||
public CosmeticItem(String id, String name, String category, String property, String value, String unlockRequirement) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.category = category;
|
||||
this.property = property;
|
||||
this.value = value;
|
||||
this.unlockRequirement = unlockRequirement;
|
||||
}
|
||||
|
||||
public boolean isUnlocked(Usuario user) {
|
||||
if (user == null) return false;
|
||||
|
||||
switch (id) {
|
||||
case "effect_fire":
|
||||
return user.streak >= 7;
|
||||
case "effect_glow":
|
||||
return user.xp >= 5000;
|
||||
case "clothes_outfit":
|
||||
return user.xp >= 1000;
|
||||
case "frame_gold":
|
||||
return "Ouro".equalsIgnoreCase(user.league) || "Gold".equalsIgnoreCase(user.league) || user.xp >= 3000;
|
||||
case "accessory_cap":
|
||||
return user.total_tasks_concluidas >= 50;
|
||||
case "accessory_headphones":
|
||||
return user.tempo_foco_total >= 600; // 10 horas * 60 minutos
|
||||
default:
|
||||
return true; // Itens normais estão sempre desbloqueados
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,12 @@ public class FindFriendsActivity extends AppCompatActivity {
|
||||
tvName.setText(user.usuario);
|
||||
tvStats.setText("Nível " + user.level + " • " + user.xp + " XP");
|
||||
|
||||
AvatarView ivAvatar = view.findViewById(R.id.ivFriendAvatar);
|
||||
if (ivAvatar != null && user.avatar != null) {
|
||||
ivAvatar.setAvatarData(user.avatar);
|
||||
ivAvatar.setLeague(user.league);
|
||||
}
|
||||
|
||||
btnAction.setOnClickListener(v -> {
|
||||
btnAction.setText("Pendente");
|
||||
btnAction.setEnabled(false);
|
||||
|
||||
@@ -40,6 +40,7 @@ public class InicioFragment extends Fragment {
|
||||
private FocusState currentFocusState = FocusState.NOT_STARTED;
|
||||
|
||||
private TextView tvTimer, tvGreeting, tvMotivationalSubtitle, tvFocusStatus, tvFocusTitle;
|
||||
private AvatarView ivUserAvatar;
|
||||
private TextView tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
|
||||
private TextView tvDailyRewardGoal;
|
||||
private ProgressBar pbDailyTasksProgress;
|
||||
@@ -90,6 +91,7 @@ public class InicioFragment extends Fragment {
|
||||
// Header
|
||||
tvGreeting = view.findViewById(R.id.tvGreeting);
|
||||
tvMotivationalSubtitle = view.findViewById(R.id.tvMotivationalSubtitle);
|
||||
ivUserAvatar = view.findViewById(R.id.ivUserAvatar);
|
||||
view.findViewById(R.id.cardProfileAvatar).setOnClickListener(v -> {
|
||||
if (getActivity() instanceof MainActivity) {
|
||||
BottomNavigationView nav = ((MainActivity) getActivity()).findViewById(R.id.bottom_navigation);
|
||||
@@ -193,6 +195,10 @@ public class InicioFragment extends Fragment {
|
||||
if (tvGreeting != null) {
|
||||
tvGreeting.setText("Olá, " + user.usuario + "!");
|
||||
}
|
||||
if (ivUserAvatar != null && user.avatar != null) {
|
||||
ivUserAvatar.setAvatarData(user.avatar);
|
||||
ivUserAvatar.setLeague(user.league);
|
||||
}
|
||||
|
||||
refreshHomeStats();
|
||||
|
||||
@@ -535,23 +541,28 @@ public class InicioFragment extends Fragment {
|
||||
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) {
|
||||
Usuario u = doc.toObject(Usuario.class);
|
||||
if (u != null) {
|
||||
addMiniRankingItem(rank++, u.usuario, u.xp_hoje);
|
||||
addMiniRankingItem(rank++, u);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addMiniRankingItem(int rank, String name, int xp) {
|
||||
private void addMiniRankingItem(int rank, Usuario u) {
|
||||
if (getContext() == null || miniRankingContainer == null) return;
|
||||
|
||||
View item = getLayoutInflater().inflate(R.layout.item_ranking_user, miniRankingContainer, false);
|
||||
TextView tvRank = item.findViewById(R.id.tvRankPosition);
|
||||
TextView tvName = item.findViewById(R.id.tvRankingName);
|
||||
TextView tvXP = item.findViewById(R.id.tvRankingXP);
|
||||
AvatarView ivAvatar = item.findViewById(R.id.ivRankingAvatar);
|
||||
|
||||
tvRank.setText("#" + rank);
|
||||
tvName.setText(name);
|
||||
tvXP.setText(xp + " XP");
|
||||
tvName.setText(u.usuario);
|
||||
tvXP.setText(u.xp_hoje + " XP");
|
||||
if (ivAvatar != null && u.avatar != null) {
|
||||
ivAvatar.setAvatarData(u.avatar);
|
||||
ivAvatar.setLeague(u.league);
|
||||
}
|
||||
|
||||
// Remove elevation for mini ranking to keep it clean
|
||||
if (item instanceof androidx.cardview.widget.CardView) {
|
||||
|
||||
@@ -88,6 +88,12 @@ public class MyFriendsActivity extends AppCompatActivity {
|
||||
tvLabel.setVisibility(View.VISIBLE);
|
||||
tvLabel.setTextColor(getResources().getColor(R.color.primary_purple));
|
||||
|
||||
AvatarView ivAvatar = view.findViewById(R.id.ivRankingAvatar);
|
||||
if (ivAvatar != null && friend.avatar != null) {
|
||||
ivAvatar.setAvatarData(friend.avatar);
|
||||
ivAvatar.setLeague(friend.league);
|
||||
}
|
||||
|
||||
view.setOnClickListener(v -> {
|
||||
// Open public profile (future)
|
||||
Toast.makeText(this, "Perfil de " + friend.usuario, Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -43,7 +43,8 @@ import java.util.Locale;
|
||||
public class ProfileFragment extends Fragment {
|
||||
|
||||
private TextView tvProfileName, tvProfileHandle;
|
||||
private ImageView ivProfileAvatar, ivLeagueBadgeSmall, ivLeagueIcon;
|
||||
private AvatarView ivProfileAvatar;
|
||||
private ImageView ivLeagueBadgeSmall, ivLeagueIcon;
|
||||
private TextView tvUserLevel, tvXpFraction, tvLeagueName, tvLeagueMotivation, tvConsistencyPhrase;
|
||||
private ProgressBar pbXpLevel;
|
||||
private RecyclerView rvMiniCalendar;
|
||||
@@ -124,6 +125,12 @@ public class ProfileFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
// Avatar Editor
|
||||
View cardAvatar = view.findViewById(R.id.cardAvatar);
|
||||
if (cardAvatar != null) {
|
||||
cardAvatar.setOnClickListener(v -> startActivity(new Intent(getActivity(), AvatarEditorActivity.class)));
|
||||
}
|
||||
|
||||
// Add Friends (+)
|
||||
View btnAddFriends = view.findViewById(R.id.btnAddFriends);
|
||||
if (btnAddFriends != null) {
|
||||
@@ -182,6 +189,10 @@ public class ProfileFragment extends Fragment {
|
||||
private void updateBasicInfo(Usuario user) {
|
||||
tvProfileName.setText(user.usuario);
|
||||
tvProfileHandle.setText(user.handle);
|
||||
if (user.avatar != null && ivProfileAvatar != null) {
|
||||
ivProfileAvatar.setAvatarData(user.avatar);
|
||||
ivProfileAvatar.setLeague(user.league);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateXpBar(Usuario user) {
|
||||
@@ -201,10 +212,10 @@ public class ProfileFragment extends Fragment {
|
||||
int progressPercent = (int) ((progressInLevel * 100.0f) / levelXpSpan);
|
||||
|
||||
// Animate Progress Bar
|
||||
ObjectAnimator.ofInt(pbXpLevel, "progress", pbXpLevel.getProgress(), progressPercent)
|
||||
.setDuration(1000)
|
||||
.setInterpolator(new DecelerateInterpolator())
|
||||
.start();
|
||||
ObjectAnimator animator = ObjectAnimator.ofInt(pbXpLevel, "progress", pbXpLevel.getProgress(), progressPercent);
|
||||
animator.setDuration(1000);
|
||||
animator.setInterpolator(new DecelerateInterpolator());
|
||||
animator.start();
|
||||
}
|
||||
|
||||
private int calculateLevel(int totalXp) {
|
||||
@@ -422,6 +433,12 @@ public class ProfileFragment extends Fragment {
|
||||
if (tvStreak != null) {
|
||||
tvStreak.setText("🔥 " + friend.streak);
|
||||
}
|
||||
|
||||
AvatarView ivAvatar = v.findViewById(R.id.ivRankingAvatar);
|
||||
if (ivAvatar != null && friend.avatar != null) {
|
||||
ivAvatar.setAvatarData(friend.avatar);
|
||||
ivAvatar.setLeague(friend.league);
|
||||
}
|
||||
|
||||
// Gamify friend item
|
||||
TextView tvRank = v.findViewById(R.id.tvRankPosition);
|
||||
|
||||
@@ -310,7 +310,10 @@ public class SearchFragment extends Fragment {
|
||||
Usuario user = items.get(position);
|
||||
holder.name.setText(user.usuario);
|
||||
holder.stats.setText("🔥 " + user.streak + " dias • " + user.league);
|
||||
// holder.avatar setup if needed
|
||||
if (holder.avatar != null && user.avatar != null) {
|
||||
holder.avatar.setAvatarData(user.avatar);
|
||||
holder.avatar.setLeague(user.league);
|
||||
}
|
||||
holder.btnAdd.setOnClickListener(v -> Toast.makeText(getContext(), "Pedido enviado!", Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
@@ -318,7 +321,7 @@ public class SearchFragment extends Fragment {
|
||||
public int getItemCount() { return items.size(); }
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView avatar;
|
||||
AvatarView avatar;
|
||||
TextView name, stats;
|
||||
View btnAdd;
|
||||
ViewHolder(View v) {
|
||||
|
||||
@@ -136,6 +136,11 @@ public class TrophiesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
// Bottom Card
|
||||
AvatarView ivAvatar = findViewById(R.id.ivUserAvatar);
|
||||
if (ivAvatar != null && user.avatar != null) {
|
||||
ivAvatar.setAvatarData(user.avatar);
|
||||
ivAvatar.setLeague(user.league);
|
||||
}
|
||||
tvUserName.setText(user.usuario);
|
||||
tvUserDivision.setText(current.name + " • " + user.xp + " XP");
|
||||
if (next != null) {
|
||||
@@ -243,10 +248,15 @@ public class TrophiesActivity extends AppCompatActivity {
|
||||
TextView tvXP = view.findViewById(R.id.tvRankingXP);
|
||||
TextView tvTu = view.findViewById(R.id.tvRankingLabelTu);
|
||||
androidx.cardview.widget.CardView card = view.findViewById(R.id.cardRankingUser);
|
||||
AvatarView ivAvatar = view.findViewById(R.id.ivRankingAvatar);
|
||||
|
||||
tvPos.setText("#" + pos);
|
||||
tvName.setText(user.usuario);
|
||||
tvXP.setText(user.xp_semanal + " XP");
|
||||
if (ivAvatar != null && user.avatar != null) {
|
||||
ivAvatar.setAvatarData(user.avatar);
|
||||
ivAvatar.setLeague(user.league);
|
||||
}
|
||||
|
||||
if (user.id_usuario.equals(myUid)) {
|
||||
tvTu.setVisibility(View.VISIBLE);
|
||||
|
||||
42
app/src/main/java/com/fluxup/app/UnlockManager.java
Normal file
42
app/src/main/java/com/fluxup/app/UnlockManager.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.fluxup.app;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UnlockManager {
|
||||
private static List<CosmeticItem> items;
|
||||
|
||||
public static List<CosmeticItem> getLockedCosmetics() {
|
||||
if (items == null) {
|
||||
items = new ArrayList<>();
|
||||
// 🔥 7 dias ofensiva -> aura de fogo
|
||||
items.add(new CosmeticItem("effect_fire", "Aura de Fogo", "efeitos", "effect", "fire_aura", "Desbloqueia com 7 dias de ofensiva"));
|
||||
// ⚡ 5000 XP -> brilho especial
|
||||
items.add(new CosmeticItem("effect_glow", "Brilho Roxo", "efeitos", "effect", "glow", "Desbloqueia com 5000 XP"));
|
||||
// ⚡ 1000 XP -> roupa premium (outfit)
|
||||
items.add(new CosmeticItem("clothes_outfit", "Casaco Premium", "roupa", "clothesStyle", "outfit", "Desbloqueia com 1000 XP"));
|
||||
// 🏆 Liga Ouro -> moldura dourada
|
||||
items.add(new CosmeticItem("frame_gold", "Moldura Dourada", "molduras", "frame", "gold", "Desbloqueia na Liga Ouro"));
|
||||
// 🎯 50 tarefas concluídas -> boné de campeão
|
||||
items.add(new CosmeticItem("accessory_cap", "Boné de Campeão", "acessorios", "accessory", "cap", "Desbloqueia com 50 tarefas concluídas"));
|
||||
// ⏱ 10h de foco -> headphones de foco
|
||||
items.add(new CosmeticItem("accessory_headphones", "Headphones de Foco", "acessorios", "accessory", "headphones", "Desbloqueia com 10h de foco"));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public static CosmeticItem findCosmetic(String property, String value) {
|
||||
for (CosmeticItem item : getLockedCosmetics()) {
|
||||
if (item.property.equals(property) && item.value.equals(value)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isItemLockedForUser(Usuario user, String property, String value) {
|
||||
CosmeticItem item = findCosmetic(property, value);
|
||||
if (item == null) return false; // Se não estiver na lista de bloqueados, está livre
|
||||
return !item.isUnlocked(user);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ public class Usuario {
|
||||
public String last_streak_completed_date = ""; // YYYY-MM-DD
|
||||
public String last_reward_claim_date = ""; // YYYY-MM-DD
|
||||
public String avatar_url = "";
|
||||
public AvatarData avatar = new AvatarData(); // Avatar gamificado
|
||||
public java.util.List<String> dias_concluidos = new java.util.ArrayList<>();
|
||||
|
||||
public Usuario() {}
|
||||
|
||||
7
app/src/main/res/drawable/chart_fill_gradient.xml
Normal file
7
app/src/main/res/drawable/chart_fill_gradient.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:startColor="#407C3AED"
|
||||
android:endColor="#007C3AED"
|
||||
android:angle="270" />
|
||||
</shape>
|
||||
20
app/src/main/res/drawable/xp_progress_bar.xml
Normal file
20
app/src/main/res/drawable/xp_progress_bar.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="12dp" />
|
||||
<solid android:color="#E5E7EB" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<scale android:scaleWidth="100%">
|
||||
<shape>
|
||||
<corners android:radius="12dp" />
|
||||
<gradient
|
||||
android:startColor="#A35AFF"
|
||||
android:endColor="#7C3AED"
|
||||
android:angle="0" />
|
||||
</shape>
|
||||
</scale>
|
||||
</item>
|
||||
</layer-list>
|
||||
201
app/src/main/res/layout/activity_avatar_editor.xml
Normal file
201
app/src/main/res/layout/activity_avatar_editor.xml
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<!-- HEADER -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:background="@color/card_background"
|
||||
android:elevation="4dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnBackEditor"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_back"
|
||||
app:tint="@color/text_primary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Avatar"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSaveTop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="Guardar"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:textColor="@color/primary_purple"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- AVATAR PREVIEW -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#F8FAFC">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="220dp"
|
||||
android:layout_height="220dp"
|
||||
android:layout_gravity="center"
|
||||
app:cardCornerRadius="110dp"
|
||||
app:cardElevation="12dp">
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/previewAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- EDITOR BOTTOM SHEET -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/card_background"
|
||||
android:elevation="16dp">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabsCategories"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:tabMode="scrollable"
|
||||
app:tabIndicatorColor="@color/primary_purple"
|
||||
app:tabSelectedTextColor="@color/primary_purple"
|
||||
app:tabTextColor="@color/text_secondary">
|
||||
|
||||
<com.google.android.material.tabs.TabItem android:text="Corpo" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Cabelo" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Rosto" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Roupa" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Acessórios" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Molduras" />
|
||||
<com.google.android.material.tabs.TabItem android:text="Efeitos" />
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
<!-- OPTIONS CONTAINER -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- CORPO -->
|
||||
<ScrollView android:id="@+id/panelCorpo" android:layout_width="match_parent" android:layout_height="match_parent">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Tom de Pele" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llSkinColors" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Formato do Corpo" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llBodyFormats" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- CABELO -->
|
||||
<ScrollView android:id="@+id/panelCabelo" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Estilo de Cabelo" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llHairStyles" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Cor do Cabelo" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llHairColors" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- ROSTO -->
|
||||
<ScrollView android:id="@+id/panelRosto" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Olhos" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llEyes" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Sobrancelhas" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llEyebrows" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Boca" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llMouth" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Barba" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llBeard" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- ROUPA -->
|
||||
<ScrollView android:id="@+id/panelRoupa" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Estilo" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp">
|
||||
<LinearLayout android:id="@+id/llClothes" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView android:text="Cor" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llClothesColors" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- ACESSÓRIOS -->
|
||||
<ScrollView android:id="@+id/panelAcessorios" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Cabeça / Rosto" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llAccessories" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- MOLDURAS -->
|
||||
<ScrollView android:id="@+id/panelMolduras" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Molduras Especiais" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llFrames" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- EFEITOS -->
|
||||
<ScrollView android:id="@+id/panelEfeitos" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone">
|
||||
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<TextView android:text="Auras e Efeitos" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp"/>
|
||||
<HorizontalScrollView android:scrollbars="none" android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||
<LinearLayout android:id="@+id/llEffects" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -197,12 +197,10 @@
|
||||
android:layout_height="48dp"
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardElevation="0dp">
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivUserAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -53,13 +53,10 @@
|
||||
app:cardCornerRadius="28dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivUserAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile"
|
||||
app:tint="@color/primary_purple" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
@@ -50,12 +50,10 @@
|
||||
android:layout_centerInParent="true"
|
||||
app:cardCornerRadius="55dp"
|
||||
app:cardElevation="8dp">
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivProfileAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<ImageView
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivUserAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
android:layout_height="50dp"
|
||||
app:cardCornerRadius="25dp"
|
||||
app:cardElevation="0dp">
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivFriendAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -22,13 +22,10 @@
|
||||
app:cardCornerRadius="32dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivFriendAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile"
|
||||
app:tint="@color/primary_purple" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
|
||||
25
app/src/main/res/layout/item_mini_calendar_day.xml
Normal file
25
app/src/main/res/layout/item_mini_calendar_day.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDayName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="S"
|
||||
android:textSize="10sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/vDayIndicator"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:background="@drawable/node_circle_bg"
|
||||
android:backgroundTint="#E0E0E0" />
|
||||
|
||||
</LinearLayout>
|
||||
45
app/src/main/res/layout/item_profile_stat_modern.xml
Normal file
45
app/src/main/res/layout/item_profile_stat_modern.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="1dp"
|
||||
app:cardBackgroundColor="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStatIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="🎯"
|
||||
android:textSize="20sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStatValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="120"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/text_primary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStatLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tarefas"
|
||||
android:textSize="11sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textAllCaps="true"
|
||||
android:letterSpacing="0.05"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
@@ -31,12 +31,10 @@
|
||||
android:layout_marginStart="8dp"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardElevation="0dp">
|
||||
<ImageView
|
||||
<com.fluxup.app.AvatarView
|
||||
android:id="@+id/ivRankingAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
Reference in New Issue
Block a user