Showing
34 changed files
with
717 additions
and
2 deletions
This diff is collapsed. Click to expand it.
1 | +package ly.warp.sdk.io.adapters; | ||
2 | + | ||
3 | +import android.content.Context; | ||
4 | +import android.util.TypedValue; | ||
5 | +import android.view.LayoutInflater; | ||
6 | +import android.view.View; | ||
7 | +import android.view.ViewGroup; | ||
8 | +import android.widget.ImageView; | ||
9 | +import android.widget.TextView; | ||
10 | + | ||
11 | +import androidx.annotation.NonNull; | ||
12 | +import androidx.recyclerview.widget.RecyclerView; | ||
13 | + | ||
14 | +import com.bumptech.glide.Glide; | ||
15 | +import com.bumptech.glide.load.resource.bitmap.CenterCrop; | ||
16 | + | ||
17 | +import java.util.List; | ||
18 | + | ||
19 | +import ly.warp.sdk.R; | ||
20 | +import ly.warp.sdk.io.models.DummyDataProvider; | ||
21 | +import ly.warp.sdk.io.models.OfferItem; | ||
22 | +import ly.warp.sdk.utils.TopRoundedCornersTransformation; | ||
23 | + | ||
24 | +/** | ||
25 | + * Adapter for displaying offer items in a RecyclerView | ||
26 | + */ | ||
27 | +public class OfferAdapter extends RecyclerView.Adapter<OfferAdapter.OfferViewHolder> { | ||
28 | + | ||
29 | + private final List<OfferItem> offerItems; | ||
30 | + private final Context context; | ||
31 | + private OnOfferClickListener listener; | ||
32 | + | ||
33 | + /** | ||
34 | + * Interface for handling offer item clicks | ||
35 | + */ | ||
36 | + public interface OnOfferClickListener { | ||
37 | + void onOfferClick(OfferItem offerItem, int position); | ||
38 | + void onFavoriteClick(OfferItem offerItem, int position); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * Constructor | ||
43 | + * | ||
44 | + * @param context The context | ||
45 | + * @param offerItems List of offer items to display | ||
46 | + */ | ||
47 | + public OfferAdapter(Context context, List<OfferItem> offerItems) { | ||
48 | + this.context = context; | ||
49 | + this.offerItems = offerItems; | ||
50 | + } | ||
51 | + | ||
52 | + /** | ||
53 | + * Set click listener for offer items | ||
54 | + * | ||
55 | + * @param listener The listener | ||
56 | + */ | ||
57 | + public void setOnOfferClickListener(OnOfferClickListener listener) { | ||
58 | + this.listener = listener; | ||
59 | + } | ||
60 | + | ||
61 | + @NonNull | ||
62 | + @Override | ||
63 | + public OfferViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { | ||
64 | + View view = LayoutInflater.from(context).inflate(R.layout.demo_item_offer, parent, false); | ||
65 | + return new OfferViewHolder(view); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public void onBindViewHolder(@NonNull OfferViewHolder holder, int position) { | ||
70 | + OfferItem offerItem = offerItems.get(position); | ||
71 | + holder.bind(offerItem, position); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public int getItemCount() { | ||
76 | + return offerItems.size(); | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * ViewHolder for offer items | ||
81 | + */ | ||
82 | + class OfferViewHolder extends RecyclerView.ViewHolder { | ||
83 | + private final ImageView ivOfferImage; | ||
84 | + private final ImageView ivFavorite; | ||
85 | + private final ImageView ivLogo; | ||
86 | + private final TextView tvPrice; | ||
87 | + private final TextView tvTitle; | ||
88 | + private final TextView tvDescription; | ||
89 | + private final TextView tvValidity; | ||
90 | + | ||
91 | + OfferViewHolder(@NonNull View itemView) { | ||
92 | + super(itemView); | ||
93 | + ivOfferImage = itemView.findViewById(R.id.iv_offer_image); | ||
94 | + ivFavorite = itemView.findViewById(R.id.iv_favorite); | ||
95 | + ivLogo = itemView.findViewById(R.id.iv_logo); | ||
96 | + tvPrice = itemView.findViewById(R.id.tv_price); | ||
97 | + tvTitle = itemView.findViewById(R.id.tv_title); | ||
98 | + tvDescription = itemView.findViewById(R.id.tv_description); | ||
99 | + tvValidity = itemView.findViewById(R.id.tv_validity); | ||
100 | + | ||
101 | + // Set click listeners | ||
102 | +// itemView.setOnClickListener(v -> { | ||
103 | +// int position = getAdapterPosition(); | ||
104 | +// if (listener != null && position != RecyclerView.NO_POSITION) { | ||
105 | +// listener.onOfferClick(offerItems.get(position), position); | ||
106 | +// } | ||
107 | +// }); | ||
108 | + | ||
109 | +// ivFavorite.setOnClickListener(v -> { | ||
110 | +// int position = getAdapterPosition(); | ||
111 | +// if (listener != null && position != RecyclerView.NO_POSITION) { | ||
112 | +// listener.onFavoriteClick(offerItems.get(position), position); | ||
113 | +// } | ||
114 | +// }); | ||
115 | + } | ||
116 | + | ||
117 | + void bind(OfferItem offerItem, int position) { | ||
118 | + // Set offer data to views | ||
119 | + tvTitle.setText(offerItem.getTitle()); | ||
120 | + tvDescription.setText(offerItem.getDescription()); | ||
121 | + tvPrice.setText(offerItem.getValue()); | ||
122 | + tvValidity.setText(offerItem.getEndDate()); | ||
123 | + | ||
124 | + // Set heart icon based on category | ||
125 | + if (DummyDataProvider.CATEGORY_FAVORITES.equals(offerItem.getCategory())) { | ||
126 | + // Use pressed/filled heart for Favorites category | ||
127 | + ivFavorite.setImageResource(R.drawable.demo_heart_pressed); | ||
128 | + } else { | ||
129 | + // Use default/empty heart for other categories | ||
130 | + ivFavorite.setImageResource(R.drawable.demo_heart); | ||
131 | + } | ||
132 | + | ||
133 | + // Load images from resources | ||
134 | + loadOfferImage(offerItem.getImageUrl()); | ||
135 | + loadLogoImage(offerItem.getLogoUrl()); | ||
136 | + } | ||
137 | + | ||
138 | + /** | ||
139 | + * Load offer image with rounded top corners using Glide | ||
140 | + * | ||
141 | + * @param imageName The image resource name | ||
142 | + */ | ||
143 | + private void loadOfferImage(String imageName) { | ||
144 | + try { | ||
145 | + // Remove file extension if present | ||
146 | + if (imageName.contains(".")) { | ||
147 | + imageName = imageName.substring(0, imageName.lastIndexOf('.')); | ||
148 | + } | ||
149 | + | ||
150 | + // Get resource ID by name | ||
151 | + int resourceId = context.getResources().getIdentifier( | ||
152 | + imageName, "drawable", context.getPackageName()); | ||
153 | + | ||
154 | + if (resourceId != 0) { | ||
155 | + // Convert 9dp to pixels | ||
156 | + int radiusInPixels = (int) TypedValue.applyDimension( | ||
157 | + TypedValue.COMPLEX_UNIT_DIP, 9, | ||
158 | + context.getResources().getDisplayMetrics()); | ||
159 | + | ||
160 | + // Load with Glide and apply transformations | ||
161 | + Glide.with(context) | ||
162 | + .load(resourceId) | ||
163 | + .transform(new CenterCrop(), new TopRoundedCornersTransformation(radiusInPixels)) | ||
164 | + .into(ivOfferImage); | ||
165 | + } | ||
166 | + } catch (Exception e) { | ||
167 | + e.printStackTrace(); | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + /** | ||
172 | + * Load logo image without transformations | ||
173 | + * | ||
174 | + * @param imageName The image resource name | ||
175 | + */ | ||
176 | + private void loadLogoImage(String imageName) { | ||
177 | + try { | ||
178 | + // Remove file extension if present | ||
179 | + if (imageName.contains(".")) { | ||
180 | + imageName = imageName.substring(0, imageName.lastIndexOf('.')); | ||
181 | + } | ||
182 | + | ||
183 | + // Get resource ID by name | ||
184 | + int resourceId = context.getResources().getIdentifier( | ||
185 | + imageName, "drawable", context.getPackageName()); | ||
186 | + | ||
187 | + if (resourceId != 0) { | ||
188 | + // Load logo normally without transformations | ||
189 | + ivLogo.setImageResource(resourceId); | ||
190 | + } | ||
191 | + } catch (Exception e) { | ||
192 | + e.printStackTrace(); | ||
193 | + } | ||
194 | + } | ||
195 | + } | ||
196 | +} |
This diff is collapsed. Click to expand it.
1 | +package ly.warp.sdk.io.models; | ||
2 | + | ||
3 | +import java.io.Serializable; | ||
4 | +import java.util.ArrayList; | ||
5 | +import java.util.List; | ||
6 | + | ||
7 | +/** | ||
8 | + * Model class representing a category of offers with its associated items. | ||
9 | + */ | ||
10 | +public class OfferCategory implements Serializable { | ||
11 | + private String id; | ||
12 | + private String name; | ||
13 | + private List<OfferItem> items; | ||
14 | + | ||
15 | + /** | ||
16 | + * Default constructor | ||
17 | + */ | ||
18 | + public OfferCategory() { | ||
19 | + this.items = new ArrayList<>(); | ||
20 | + } | ||
21 | + | ||
22 | + /** | ||
23 | + * Constructor with id and name | ||
24 | + * | ||
25 | + * @param id Unique identifier for the category | ||
26 | + * @param name Display name of the category | ||
27 | + */ | ||
28 | + public OfferCategory(String id, String name) { | ||
29 | + this.id = id; | ||
30 | + this.name = name; | ||
31 | + this.items = new ArrayList<>(); | ||
32 | + } | ||
33 | + | ||
34 | + /** | ||
35 | + * Full constructor | ||
36 | + * | ||
37 | + * @param id Unique identifier for the category | ||
38 | + * @param name Display name of the category | ||
39 | + * @param items List of offer items in this category | ||
40 | + */ | ||
41 | + public OfferCategory(String id, String name, List<OfferItem> items) { | ||
42 | + this.id = id; | ||
43 | + this.name = name; | ||
44 | + this.items = items != null ? items : new ArrayList<>(); | ||
45 | + } | ||
46 | + | ||
47 | + // Getters and Setters | ||
48 | + | ||
49 | + public String getId() { | ||
50 | + return id; | ||
51 | + } | ||
52 | + | ||
53 | + public void setId(String id) { | ||
54 | + this.id = id; | ||
55 | + } | ||
56 | + | ||
57 | + public String getName() { | ||
58 | + return name; | ||
59 | + } | ||
60 | + | ||
61 | + public void setName(String name) { | ||
62 | + this.name = name; | ||
63 | + } | ||
64 | + | ||
65 | + public List<OfferItem> getItems() { | ||
66 | + return items; | ||
67 | + } | ||
68 | + | ||
69 | + public void setItems(List<OfferItem> items) { | ||
70 | + this.items = items != null ? items : new ArrayList<>(); | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Add a single item to the category | ||
75 | + * | ||
76 | + * @param item The offer item to add | ||
77 | + */ | ||
78 | + public void addItem(OfferItem item) { | ||
79 | + if (items == null) { | ||
80 | + items = new ArrayList<>(); | ||
81 | + } | ||
82 | + items.add(item); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Get the number of items in this category | ||
87 | + * | ||
88 | + * @return The count of items | ||
89 | + */ | ||
90 | + public int getItemCount() { | ||
91 | + return items != null ? items.size() : 0; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * Get the formatted name with item count | ||
96 | + * | ||
97 | + * @return Category name with item count in parentheses | ||
98 | + */ | ||
99 | + public String getFormattedName() { | ||
100 | + return name + " (" + getItemCount() + ")"; | ||
101 | + } | ||
102 | +} |
1 | +package ly.warp.sdk.io.models; | ||
2 | + | ||
3 | +import java.io.Serializable; | ||
4 | + | ||
5 | +/** | ||
6 | + * Model class representing an offer item to be displayed in the home screen. | ||
7 | + */ | ||
8 | +public class OfferItem implements Serializable { | ||
9 | + private String id; | ||
10 | + private String title; | ||
11 | + private String description; | ||
12 | + private String endDate; | ||
13 | + private String value; | ||
14 | + private String imageUrl; | ||
15 | + private String logoUrl; | ||
16 | + private String category; | ||
17 | + | ||
18 | + /** | ||
19 | + * Default constructor | ||
20 | + */ | ||
21 | + public OfferItem() { | ||
22 | + } | ||
23 | + | ||
24 | + /** | ||
25 | + * Full constructor for creating an offer item | ||
26 | + * | ||
27 | + * @param id Unique identifier for the offer | ||
28 | + * @param title Title of the offer | ||
29 | + * @param description Description of the offer | ||
30 | + * @param endDate End date of the offer (formatted as string) | ||
31 | + * @param value Value of the offer (formatted as string, e.g., "50%", "€20") | ||
32 | + * @param imageUrl URL or resource name for the offer image | ||
33 | + * @param logoUrl URL or resource name for the merchant logo | ||
34 | + * @param category Category this offer belongs to | ||
35 | + */ | ||
36 | + public OfferItem(String id, String title, String description, String endDate, | ||
37 | + String value, String imageUrl, String logoUrl, String category) { | ||
38 | + this.id = id; | ||
39 | + this.title = title; | ||
40 | + this.description = description; | ||
41 | + this.endDate = endDate; | ||
42 | + this.value = value; | ||
43 | + this.imageUrl = imageUrl; | ||
44 | + this.logoUrl = logoUrl; | ||
45 | + this.category = category; | ||
46 | + } | ||
47 | + | ||
48 | + // Getters and Setters | ||
49 | + | ||
50 | + public String getId() { | ||
51 | + return id; | ||
52 | + } | ||
53 | + | ||
54 | + public void setId(String id) { | ||
55 | + this.id = id; | ||
56 | + } | ||
57 | + | ||
58 | + public String getTitle() { | ||
59 | + return title; | ||
60 | + } | ||
61 | + | ||
62 | + public void setTitle(String title) { | ||
63 | + this.title = title; | ||
64 | + } | ||
65 | + | ||
66 | + public String getDescription() { | ||
67 | + return description; | ||
68 | + } | ||
69 | + | ||
70 | + public void setDescription(String description) { | ||
71 | + this.description = description; | ||
72 | + } | ||
73 | + | ||
74 | + public String getEndDate() { | ||
75 | + return endDate; | ||
76 | + } | ||
77 | + | ||
78 | + public void setEndDate(String endDate) { | ||
79 | + this.endDate = endDate; | ||
80 | + } | ||
81 | + | ||
82 | + public String getValue() { | ||
83 | + return value; | ||
84 | + } | ||
85 | + | ||
86 | + public void setValue(String value) { | ||
87 | + this.value = value; | ||
88 | + } | ||
89 | + | ||
90 | + public String getImageUrl() { | ||
91 | + return imageUrl; | ||
92 | + } | ||
93 | + | ||
94 | + public void setImageUrl(String imageUrl) { | ||
95 | + this.imageUrl = imageUrl; | ||
96 | + } | ||
97 | + | ||
98 | + public String getLogoUrl() { | ||
99 | + return logoUrl; | ||
100 | + } | ||
101 | + | ||
102 | + public void setLogoUrl(String logoUrl) { | ||
103 | + this.logoUrl = logoUrl; | ||
104 | + } | ||
105 | + | ||
106 | + public String getCategory() { | ||
107 | + return category; | ||
108 | + } | ||
109 | + | ||
110 | + public void setCategory(String category) { | ||
111 | + this.category = category; | ||
112 | + } | ||
113 | + | ||
114 | + /** | ||
115 | + * Returns the value (already formatted with % or € symbol) | ||
116 | + * @return Value string | ||
117 | + */ | ||
118 | + public String getFormattedValue() { | ||
119 | + return value; | ||
120 | + } | ||
121 | +} |
1 | +package ly.warp.sdk.utils; | ||
2 | + | ||
3 | +import android.graphics.Bitmap; | ||
4 | +import android.graphics.BitmapShader; | ||
5 | +import android.graphics.Canvas; | ||
6 | +import android.graphics.Paint; | ||
7 | +import android.graphics.Path; | ||
8 | +import android.graphics.RectF; | ||
9 | +import android.graphics.Shader; | ||
10 | + | ||
11 | +import androidx.annotation.NonNull; | ||
12 | + | ||
13 | +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; | ||
14 | +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; | ||
15 | + | ||
16 | +import java.security.MessageDigest; | ||
17 | + | ||
18 | +/** | ||
19 | + * Glide transformation to round only the top corners of an image | ||
20 | + */ | ||
21 | +public class TopRoundedCornersTransformation extends BitmapTransformation { | ||
22 | + private static final String ID = "ly.warp.sdk.utils.TopRoundedCornersTransformation"; | ||
23 | + private final int radius; | ||
24 | + | ||
25 | + /** | ||
26 | + * Constructor | ||
27 | + * | ||
28 | + * @param radius Corner radius in pixels | ||
29 | + */ | ||
30 | + public TopRoundedCornersTransformation(int radius) { | ||
31 | + this.radius = radius; | ||
32 | + } | ||
33 | + | ||
34 | + @Override | ||
35 | + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { | ||
36 | + return roundTopCorners(pool, toTransform); | ||
37 | + } | ||
38 | + | ||
39 | + private Bitmap roundTopCorners(BitmapPool pool, Bitmap source) { | ||
40 | + if (source == null) return null; | ||
41 | + | ||
42 | + Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); | ||
43 | + if (result == null) { | ||
44 | + result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); | ||
45 | + } | ||
46 | + | ||
47 | + Canvas canvas = new Canvas(result); | ||
48 | + Paint paint = new Paint(); | ||
49 | + paint.setAntiAlias(true); | ||
50 | + paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); | ||
51 | + | ||
52 | + // Create path with rounded top corners | ||
53 | + Path path = new Path(); | ||
54 | + RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight()); | ||
55 | + float[] radii = new float[]{ | ||
56 | + radius, radius, // top-left | ||
57 | + radius, radius, // top-right | ||
58 | + 0, 0, // bottom-right | ||
59 | + 0, 0 // bottom-left | ||
60 | + }; | ||
61 | + path.addRoundRect(rectF, radii, Path.Direction.CW); | ||
62 | + | ||
63 | + // Draw rounded rectangle | ||
64 | + canvas.drawPath(path, paint); | ||
65 | + | ||
66 | + return result; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { | ||
71 | + messageDigest.update((ID + radius).getBytes()); | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public boolean equals(Object o) { | ||
76 | + if (this == o) return true; | ||
77 | + if (o == null || getClass() != o.getClass()) return false; | ||
78 | + TopRoundedCornersTransformation that = (TopRoundedCornersTransformation) o; | ||
79 | + return radius == that.radius; | ||
80 | + } | ||
81 | + | ||
82 | + @Override | ||
83 | + public int hashCode() { | ||
84 | + return ID.hashCode() + radius; | ||
85 | + } | ||
86 | +} |
... | @@ -167,6 +167,30 @@ public class WarplyManagerHelper { | ... | @@ -167,6 +167,30 @@ public class WarplyManagerHelper { |
167 | context.startActivity(WarpViewActivity.createIntentFromURL(context, (WarplyProperty.getSupermarketsUrl(context) + WarpConstants.SUPERMARKETS_MAP))); | 167 | context.startActivity(WarpViewActivity.createIntentFromURL(context, (WarplyProperty.getSupermarketsUrl(context) + WarpConstants.SUPERMARKETS_MAP))); |
168 | } | 168 | } |
169 | 169 | ||
170 | + public static void openContest(Context context) { | ||
171 | + final String mContestUrl = "https://warply.s3.amazonaws.com/dei/campaigns/DehEasterContest_stage/index.html"; | ||
172 | + JSONObject params = new JSONObject(); | ||
173 | + try { | ||
174 | + params.putOpt("web_id", WarpUtils.getWebId(context)); | ||
175 | + params.putOpt("app_uuid", WarplyProperty.getAppUuid(context)); | ||
176 | + params.putOpt("api_key", WarpUtils.getApiKey(context)); | ||
177 | + params.putOpt("session_uuid", ""); | ||
178 | + params.putOpt("access_token", WarplyDBHelper.getInstance(context).getAuthValue("access_token")); | ||
179 | + params.putOpt("refresh_token", WarplyDBHelper.getInstance(context).getAuthValue("refresh_token")); | ||
180 | + params.putOpt("client_id", WarplyDBHelper.getInstance(context).getClientValue("client_id")); | ||
181 | + params.putOpt("client_secret", WarplyDBHelper.getInstance(context).getClientValue("client_secret")); | ||
182 | + params.putOpt("map", "true"); | ||
183 | + params.putOpt("lan", WarpUtils.getApplicationLocale(context)); | ||
184 | + params.putOpt("dark", String.valueOf(WarpUtils.getIsDarkModeEnabled(context))); | ||
185 | + } catch (JSONException e) { | ||
186 | + e.printStackTrace(); | ||
187 | + } | ||
188 | + | ||
189 | + WarpUtils.setWebviewParams(context, params); | ||
190 | + | ||
191 | + context.startActivity(WarpViewActivity.createIntentFromURL(context, mContestUrl)); | ||
192 | + } | ||
193 | + | ||
170 | // =========================================================== | 194 | // =========================================================== |
171 | // Inner and Anonymous Classes | 195 | // Inner and Anonymous Classes |
172 | // =========================================================== | 196 | // =========================================================== | ... | ... |
1 | +package ly.warp.sdk.views; | ||
2 | + | ||
3 | +import android.graphics.Rect; | ||
4 | +import android.view.View; | ||
5 | + | ||
6 | +import androidx.annotation.NonNull; | ||
7 | +import androidx.recyclerview.widget.RecyclerView; | ||
8 | + | ||
9 | +/** | ||
10 | + * ItemDecoration for adding horizontal spacing between RecyclerView items. | ||
11 | + * Adds spacing to the right of each item except the last one. | ||
12 | + */ | ||
13 | +public class HorizontalSpaceItemDecoration extends RecyclerView.ItemDecoration { | ||
14 | + private final int spaceWidth; | ||
15 | + | ||
16 | + /** | ||
17 | + * Constructor | ||
18 | + * | ||
19 | + * @param spaceWidth Space width in pixels | ||
20 | + */ | ||
21 | + public HorizontalSpaceItemDecoration(int spaceWidth) { | ||
22 | + this.spaceWidth = spaceWidth; | ||
23 | + } | ||
24 | + | ||
25 | + @Override | ||
26 | + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { | ||
27 | + // Add spacing to the right of each item except the last one | ||
28 | + int position = parent.getChildAdapterPosition(view); | ||
29 | + if (position != RecyclerView.NO_POSITION && position != parent.getAdapter().getItemCount() - 1) { | ||
30 | + outRect.right = spaceWidth; | ||
31 | + } | ||
32 | + } | ||
33 | +} |

3.59 KB

10.3 KB

6.15 KB

1.68 KB

1.47 KB

317 KB

114 KB

170 KB

154 KB

70.3 KB

115 KB

170 KB

160 KB

8.51 KB

21 KB

3.94 KB

6.53 KB

10.2 KB
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + android:shape="rectangle"> | ||
4 | + <corners | ||
5 | + android:bottomLeftRadius="0dp" | ||
6 | + android:bottomRightRadius="0dp" | ||
7 | + android:topLeftRadius="9dp" | ||
8 | + android:topRightRadius="9dp" /> | ||
9 | + | ||
10 | + <solid android:color="@android:color/transparent" /> | ||
11 | +</shape> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + android:shape="rectangle"> | ||
4 | + <corners android:radius="4dp" /> | ||
5 | + | ||
6 | + <solid android:color="@android:color/transparent" /> | ||
7 | + <stroke | ||
8 | + android:width="1dp" | ||
9 | + android:color="@color/black2" /> | ||
10 | +</shape> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + android:shape="rectangle"> | ||
4 | + <corners android:radius="9dp" /> | ||
5 | + | ||
6 | + <solid android:color="@color/white" /> | ||
7 | + <stroke | ||
8 | + android:width="1dp" | ||
9 | + android:color="@color/grey" /> | ||
10 | +</shape> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed. Click to expand it.
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + xmlns:app="http://schemas.android.com/apk/res-auto" | ||
4 | + xmlns:tools="http://schemas.android.com/tools" | ||
5 | + android:layout_width="260dp" | ||
6 | + android:layout_height="250dp" | ||
7 | + android:background="@drawable/demo_shape_white_border_grey"> | ||
8 | + | ||
9 | + <!-- Main Offer Image --> | ||
10 | + <ImageView | ||
11 | + android:id="@+id/iv_offer_image" | ||
12 | + android:layout_width="match_parent" | ||
13 | + android:layout_height="140dp" | ||
14 | + android:scaleType="centerCrop" | ||
15 | + tools:src="@drawable/demo_home_banner" /> | ||
16 | + | ||
17 | + <!-- Heart Icon (Favorite) --> | ||
18 | + <ImageView | ||
19 | + android:id="@+id/iv_favorite" | ||
20 | + android:layout_width="32dp" | ||
21 | + android:layout_height="32dp" | ||
22 | + android:layout_margin="8dp" | ||
23 | + android:src="@drawable/demo_heart" /> | ||
24 | + | ||
25 | + <!-- Price Badge --> | ||
26 | + <TextView | ||
27 | + android:id="@+id/tv_price" | ||
28 | + android:layout_width="68dp" | ||
29 | + android:layout_height="68dp" | ||
30 | + android:layout_alignParentEnd="true" | ||
31 | + android:layout_margin="8dp" | ||
32 | + android:background="@drawable/demo_shape_pink" | ||
33 | + android:gravity="center" | ||
34 | + android:textColor="@android:color/white" | ||
35 | + android:textSize="16sp" | ||
36 | + android:textStyle="bold" | ||
37 | + tools:text="17,95€" /> | ||
38 | + | ||
39 | + <!-- Content Section --> | ||
40 | + <androidx.constraintlayout.widget.ConstraintLayout | ||
41 | + android:layout_width="match_parent" | ||
42 | + android:layout_height="match_parent" | ||
43 | + android:layout_below="@id/iv_offer_image" | ||
44 | + android:orientation="vertical" | ||
45 | + android:padding="12dp"> | ||
46 | + | ||
47 | + <androidx.constraintlayout.widget.Guideline | ||
48 | + android:id="@+id/gl_vertical_70" | ||
49 | + android:layout_width="wrap_content" | ||
50 | + android:layout_height="wrap_content" | ||
51 | + android:orientation="vertical" | ||
52 | + app:layout_constraintGuide_percent="0.7" /> | ||
53 | + | ||
54 | + <!-- Title --> | ||
55 | + <TextView | ||
56 | + android:id="@+id/tv_title" | ||
57 | + android:layout_width="0dp" | ||
58 | + android:layout_height="wrap_content" | ||
59 | + android:maxLines="1" | ||
60 | + android:textColor="@color/black2" | ||
61 | + android:textSize="16sp" | ||
62 | + android:textStyle="bold" | ||
63 | + app:layout_constraintEnd_toStartOf="@+id/gl_vertical_70" | ||
64 | + app:layout_constraintStart_toStartOf="parent" | ||
65 | + app:layout_constraintTop_toTopOf="parent" | ||
66 | + tools:text="Móvo 17,95" /> | ||
67 | + | ||
68 | + <!-- Description --> | ||
69 | + <TextView | ||
70 | + android:id="@+id/tv_description" | ||
71 | + android:layout_width="0dp" | ||
72 | + android:layout_height="wrap_content" | ||
73 | + android:layout_marginTop="2dp" | ||
74 | + android:maxLines="2" | ||
75 | + android:textColor="@color/black3" | ||
76 | + android:textSize="13sp" | ||
77 | + app:layout_constraintEnd_toStartOf="@+id/gl_vertical_70" | ||
78 | + app:layout_constraintStart_toStartOf="parent" | ||
79 | + app:layout_constraintTop_toBottomOf="@+id/tv_title" | ||
80 | + tools:text="2 πίτσες & Coca-COLA 1,5lt" /> | ||
81 | + | ||
82 | + <!-- Validity Date --> | ||
83 | + <TextView | ||
84 | + android:id="@+id/tv_validity" | ||
85 | + android:layout_width="wrap_content" | ||
86 | + android:layout_height="wrap_content" | ||
87 | + android:layout_alignParentStart="true" | ||
88 | + android:layout_centerVertical="true" | ||
89 | + android:layout_marginTop="12dp" | ||
90 | + android:maxLines="1" | ||
91 | + android:textColor="#757575" | ||
92 | + android:textSize="12sp" | ||
93 | + app:layout_constraintStart_toStartOf="parent" | ||
94 | + app:layout_constraintTop_toBottomOf="@+id/tv_description" | ||
95 | + tools:text="έως 30-09" /> | ||
96 | + | ||
97 | + <!-- Brand Logo --> | ||
98 | + <ImageView | ||
99 | + android:id="@+id/iv_logo" | ||
100 | + android:layout_width="60dp" | ||
101 | + android:layout_height="60dp" | ||
102 | + android:layout_alignParentEnd="true" | ||
103 | + android:layout_centerVertical="true" | ||
104 | + android:scaleType="centerInside" | ||
105 | + app:layout_constraintBottom_toBottomOf="parent" | ||
106 | + app:layout_constraintEnd_toEndOf="parent" | ||
107 | + app:layout_constraintTop_toTopOf="parent" | ||
108 | + tools:src="@drawable/demo_avis" /> | ||
109 | + </androidx.constraintlayout.widget.ConstraintLayout> | ||
110 | +</RelativeLayout> |
... | @@ -13,6 +13,10 @@ | ... | @@ -13,6 +13,10 @@ |
13 | <color name="blue_dark">#3A5266</color> | 13 | <color name="blue_dark">#3A5266</color> |
14 | <color name="white">#FFFFFF</color> | 14 | <color name="white">#FFFFFF</color> |
15 | <color name="cos_green5">#79BF14</color> | 15 | <color name="cos_green5">#79BF14</color> |
16 | + <color name="black2">#000F1E</color> | ||
17 | + <color name="black3">#00111B</color> | ||
18 | + <color name="grey">#CCCCCC</color> | ||
19 | + <color name="pink">#EE417D</color> | ||
16 | 20 | ||
17 | <!-- Used in styles --> | 21 | <!-- Used in styles --> |
18 | <color name="cos_light_blue">#00A5E3</color> | 22 | <color name="cos_light_blue">#00A5E3</color> | ... | ... |
1 | <resources> | 1 | <resources> |
2 | - <string name="lbl_cosmote_webview_permission_title">COSMOTE</string> | 2 | + <string name="lbl_cosmote_webview_permission_title">Demo App</string> |
3 | - <string name="lbl_cosmote_webview_permission_message">Το COSMOTE ζητάει πρόσβαση στην τοποθεσία σας.</string> | 3 | + <string name="lbl_cosmote_webview_permission_message">Το Demo App ζητάει πρόσβαση στην τοποθεσία σας.</string> |
4 | <string name="lbl_take_photo_accept">Οκ</string> | 4 | <string name="lbl_take_photo_accept">Οκ</string> |
5 | <string name="lbl_take_photo_decline">Άκυρο</string> | 5 | <string name="lbl_take_photo_decline">Άκυρο</string> |
6 | <string name="welcome_user">Γεια σου %1$s !</string> | 6 | <string name="welcome_user">Γεια σου %1$s !</string> |
... | @@ -10,4 +10,5 @@ | ... | @@ -10,4 +10,5 @@ |
10 | <string name="menu_home">Αρχική</string> | 10 | <string name="menu_home">Αρχική</string> |
11 | <string name="demo_sm_flow">Open SM Flow</string> | 11 | <string name="demo_sm_flow">Open SM Flow</string> |
12 | <string name="demo_sm_map">Open SM Map</string> | 12 | <string name="demo_sm_map">Open SM Map</string> |
13 | + <string name="demo_all">Όλα</string> | ||
13 | </resources> | 14 | </resources> | ... | ... |
-
Please register or login to post a comment