├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── demo
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── android
│ │ └── tonyvu
│ │ └── sc
│ │ └── demo
│ │ ├── MainActivity.java
│ │ ├── ProductActivity.java
│ │ ├── ShoppingCartActivity.java
│ │ ├── adapter
│ │ ├── CartItemAdapter.java
│ │ └── ProductAdapter.java
│ │ ├── constant
│ │ └── Constant.java
│ │ └── model
│ │ ├── CartItem.java
│ │ └── Product.java
│ └── res
│ ├── drawable
│ ├── htc_one_m8.jpg
│ ├── samsung_galaxy_s6.jpg
│ └── xiaomi_mi3.jpg
│ ├── layout
│ ├── activity_cart.xml
│ ├── activity_main.xml
│ ├── activity_product.xml
│ ├── adapter_cart_item.xml
│ ├── adapter_product.xml
│ ├── cart_footer.xml
│ ├── cart_header.xml
│ └── product_list_header.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-v11
│ └── styles.xml
│ ├── values-v14
│ └── styles.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── android
│ └── tonyvu
│ └── sc
│ ├── exception
│ ├── ProductNotFoundException.java
│ └── QuantityOutOfRangeException.java
│ ├── model
│ ├── Cart.java
│ └── Saleable.java
│ └── util
│ └── CartHelper.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle files
2 | .gradle/
3 | build/
4 |
5 | # Local configuration file (sdk path, etc)
6 | local.properties
7 |
8 | # IntelliJ project files
9 | *.iml
10 | .idea/
11 |
12 | # Misc
13 | .DS_Store
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Tony Vu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # android-shoppingcart
2 |
3 | An implementation of android shopping cart library project for Android.
4 |
5 | To use this library, follow these steps:
6 |
7 | Download and include `library` in your dependencies
8 |
9 | dependencies {
10 | // ...
11 | compile project(path: ':library')
12 | }
13 |
14 | For any product that you want to add in your shopping cart, create a class that extends the
15 | `Saleable` interface and implements these 2 methods:
16 |
17 | getName() // must return the product name
18 | getPrice() // must return the product price
19 |
20 | Also override `equals()` and `hashCode()` methods.
21 |
22 | Now from anywhere in your application, you can retrieve the shopping cart with
23 |
24 | Cart cart = CartHelper.getCart();
25 |
26 | After retrieving the shopping cart, the library provides various methods to manipulate the shopping
27 | cart like adding, removing, updating products or clear the entire shopping cart.
28 |
29 | For an example on how to use this library, please see the `demo` (https://github.com/tonyvu2014/android-shoppingcart/tree/master/demo) app module.
30 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.android.tonyvu.sc.demo"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile 'com.android.support:appcompat-v7:23.1.0'
24 | compile project(path: ':library')
25 | }
26 |
--------------------------------------------------------------------------------
/demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /opt/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.text.SpannableString;
7 | import android.text.style.UnderlineSpan;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.AdapterView;
11 | import android.widget.AdapterView.OnItemClickListener;
12 | import android.widget.ListView;
13 | import android.widget.TextView;
14 |
15 | import com.android.tonyvu.sc.demo.adapter.ProductAdapter;
16 | import com.android.tonyvu.sc.demo.constant.Constant;
17 | import com.android.tonyvu.sc.demo.model.Product;
18 |
19 | public class MainActivity extends AppCompatActivity {
20 | private static final String TAG = "MainActivity";
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_main);
26 |
27 | TextView tvViewShoppingCart = (TextView)findViewById(R.id.tvViewShoppingCart);
28 | SpannableString content = new SpannableString(getText(R.string.shopping_cart));
29 | content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
30 | tvViewShoppingCart.setText(content);
31 | tvViewShoppingCart.setOnClickListener(new View.OnClickListener() {
32 | @Override
33 | public void onClick(View v) {
34 | Intent intent = new Intent(MainActivity.this, ShoppingCartActivity.class);
35 | startActivity(intent);
36 | }
37 | });
38 |
39 | ListView lvProducts = (ListView) findViewById(R.id.lvProducts);
40 | lvProducts.addHeaderView(getLayoutInflater().inflate(R.layout.product_list_header, lvProducts, false));
41 |
42 | ProductAdapter productAdapter = new ProductAdapter(this);
43 | productAdapter.updateProducts(Constant.PRODUCT_LIST);
44 |
45 | lvProducts.setAdapter(productAdapter);
46 |
47 | lvProducts.setOnItemClickListener(new OnItemClickListener() {
48 |
49 | @Override
50 | public void onItemClick(AdapterView> parent, View view,
51 | int position, long id) {
52 | Product product = Constant.PRODUCT_LIST.get(position - 1);
53 | Intent intent = new Intent(MainActivity.this, ProductActivity.class);
54 | Bundle bundle = new Bundle();
55 | bundle.putSerializable("product", product);
56 | Log.d(TAG, "View product: " + product.getName());
57 | intent.putExtras(bundle);
58 | startActivity(intent);
59 | }
60 | });
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/ProductActivity.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.text.SpannableString;
7 | import android.text.style.UnderlineSpan;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.View.OnClickListener;
11 | import android.widget.ArrayAdapter;
12 | import android.widget.Button;
13 | import android.widget.Spinner;
14 | import android.widget.TextView;
15 | import android.widget.ImageView;
16 | import com.android.tonyvu.sc.demo.constant.Constant;
17 | import com.android.tonyvu.sc.demo.model.Product;
18 | import com.android.tonyvu.sc.model.Cart;
19 | import com.android.tonyvu.sc.util.CartHelper;
20 |
21 | public class ProductActivity extends AppCompatActivity {
22 | private static final String TAG = "ProductActivity";
23 |
24 | TextView tvProductName;
25 | TextView tvProductDesc;
26 | ImageView ivProductImage;
27 | Spinner spQuantity;
28 | Button bOrder;
29 | Product product;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 |
35 | setContentView(R.layout.activity_product);
36 |
37 | Bundle data = getIntent().getExtras();
38 | product = (Product) data.getSerializable("product");
39 |
40 | Log.d(TAG, "Product hashCode: " + product.hashCode());
41 |
42 | //Set Shopping Cart link
43 | setShoppingCartLink();
44 |
45 | //Retrieve views
46 | retrieveViews();
47 |
48 | //Set product properties
49 | setProductProperties();
50 |
51 | //Initialize quantity
52 | initializeQuantity();
53 |
54 | //On ordering of product
55 | onOrderProduct();
56 | }
57 |
58 | private void setShoppingCartLink() {
59 | TextView tvViewShoppingCart = (TextView)findViewById(R.id.tvViewShoppingCart);
60 | SpannableString content = new SpannableString(getText(R.string.shopping_cart));
61 | content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
62 | tvViewShoppingCart.setText(content);
63 | tvViewShoppingCart.setOnClickListener(new OnClickListener() {
64 | @Override
65 | public void onClick(View v) {
66 | Intent intent = new Intent(ProductActivity.this, ShoppingCartActivity.class);
67 | startActivity(intent);
68 | }
69 | });
70 | }
71 |
72 | private void retrieveViews() {
73 | tvProductName = (TextView) findViewById(R.id.tvProductName);
74 | tvProductDesc = (TextView) findViewById(R.id.tvProductDesc);
75 | ivProductImage = (ImageView) findViewById(R.id.ivProductImage);
76 | spQuantity = (Spinner) findViewById(R.id.spQuantity);
77 | bOrder = (Button) findViewById(R.id.bOrder);
78 | }
79 |
80 | private void setProductProperties() {
81 | tvProductName.setText(product.getName());
82 | tvProductDesc.setText(product.getDescription());
83 | ivProductImage.setImageResource(this.getResources().getIdentifier(product.getImageName(), "drawable", this.getPackageName()));
84 | }
85 |
86 | private void initializeQuantity() {
87 | ArrayAdapter dataAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, Constant.QUANTITY_LIST);
88 | dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
89 | spQuantity.setAdapter(dataAdapter);
90 | }
91 |
92 | private void onOrderProduct() {
93 | bOrder.setOnClickListener(new OnClickListener() {
94 | @Override
95 | public void onClick(View v) {
96 | Cart cart = CartHelper.getCart();
97 | Log.d(TAG, "Adding product: " + product.getName());
98 | cart.add(product, Integer.valueOf(spQuantity.getSelectedItem().toString()));
99 | Intent intent = new Intent(ProductActivity.this, ShoppingCartActivity.class);
100 | startActivity(intent);
101 | }
102 | });
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/ShoppingCartActivity.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.View.OnClickListener;
12 | import android.widget.AdapterView;
13 | import android.widget.Button;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 |
17 | import com.android.tonyvu.sc.demo.adapter.CartItemAdapter;
18 | import com.android.tonyvu.sc.demo.constant.Constant;
19 | import com.android.tonyvu.sc.demo.model.CartItem;
20 | import com.android.tonyvu.sc.demo.model.Product;
21 | import com.android.tonyvu.sc.model.Cart;
22 | import com.android.tonyvu.sc.model.Saleable;
23 | import com.android.tonyvu.sc.util.CartHelper;
24 |
25 | import java.math.BigDecimal;
26 | import java.util.ArrayList;
27 | import java.util.List;
28 | import java.util.Map;
29 | import java.util.Map.Entry;
30 |
31 | public class ShoppingCartActivity extends AppCompatActivity {
32 | private static final String TAG = "ShoppingCartActivity";
33 |
34 | ListView lvCartItems;
35 | Button bClear;
36 | Button bShop;
37 | TextView tvTotalPrice;
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.activity_cart);
43 |
44 | lvCartItems = (ListView) findViewById(R.id.lvCartItems);
45 | LayoutInflater layoutInflater = getLayoutInflater();
46 |
47 | final Cart cart = CartHelper.getCart();
48 | final TextView tvTotalPrice = (TextView) findViewById(R.id.tvTotalPrice);
49 | tvTotalPrice.setText(Constant.CURRENCY+String.valueOf(cart.getTotalPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
50 |
51 | lvCartItems.addHeaderView(layoutInflater.inflate(R.layout.cart_header, lvCartItems, false));
52 |
53 | final CartItemAdapter cartItemAdapter = new CartItemAdapter(this);
54 | cartItemAdapter.updateCartItems(getCartItems(cart));
55 |
56 | lvCartItems.setAdapter(cartItemAdapter);
57 |
58 | bClear = (Button) findViewById(R.id.bClear);
59 | bShop = (Button) findViewById(R.id.bShop);
60 |
61 | bClear.setOnClickListener(new OnClickListener() {
62 | @Override
63 | public void onClick(View v) {
64 | Log.d(TAG, "Clearing the shopping cart");
65 | cart.clear();
66 | cartItemAdapter.updateCartItems(getCartItems(cart));
67 | cartItemAdapter.notifyDataSetChanged();
68 | tvTotalPrice.setText(Constant.CURRENCY+String.valueOf(cart.getTotalPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
69 | }
70 | });
71 |
72 | bShop.setOnClickListener(new OnClickListener() {
73 | @Override
74 | public void onClick(View v) {
75 | Intent intent = new Intent(ShoppingCartActivity.this, MainActivity.class);
76 | startActivity(intent);
77 | }
78 | });
79 |
80 | lvCartItems.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
81 | @Override
82 | public boolean onItemLongClick(AdapterView> parent, View view, final int position, long id) {
83 | new AlertDialog.Builder(ShoppingCartActivity.this)
84 | .setTitle(getResources().getString(R.string.delete_item))
85 | .setMessage(getResources().getString(R.string.delete_item_message))
86 | .setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener() {
87 | @Override
88 | public void onClick(DialogInterface dialog, int which) {
89 | List cartItems = getCartItems(cart);
90 | cart.remove(cartItems.get(position-1).getProduct());
91 | cartItems.remove(position-1);
92 | cartItemAdapter.updateCartItems(cartItems);
93 | cartItemAdapter.notifyDataSetChanged();
94 | tvTotalPrice.setText(Constant.CURRENCY+String.valueOf(cart.getTotalPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
95 | }
96 | })
97 | .setNegativeButton(getResources().getString(R.string.no), null)
98 | .show();
99 | return false;
100 | }
101 | });
102 |
103 | lvCartItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
104 | @Override
105 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
106 | Bundle bundle = new Bundle();
107 | List cartItems = getCartItems(cart);
108 | Product product = cartItems.get(position-1).getProduct();
109 | Log.d(TAG, "Viewing product: " + product.getName());
110 | bundle.putSerializable("product", product);
111 | Intent intent = new Intent(ShoppingCartActivity.this, ProductActivity.class);
112 | intent.putExtras(bundle);
113 | startActivity(intent);
114 | }
115 | });
116 | }
117 |
118 | private List getCartItems(Cart cart) {
119 | List cartItems = new ArrayList();
120 | Log.d(TAG, "Current shopping cart: " + cart);
121 |
122 | Map itemMap = cart.getItemWithQuantity();
123 |
124 | for (Entry entry : itemMap.entrySet()) {
125 | CartItem cartItem = new CartItem();
126 | cartItem.setProduct((Product) entry.getKey());
127 | cartItem.setQuantity(entry.getValue());
128 | cartItems.add(cartItem);
129 | }
130 |
131 | Log.d(TAG, "Cart item list: " + cartItems);
132 | return cartItems;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/adapter/CartItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo.adapter;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | import android.content.Context;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.BaseAdapter;
12 | import android.widget.TextView;
13 |
14 | import com.android.tonyvu.sc.demo.R;
15 | import com.android.tonyvu.sc.demo.constant.Constant;
16 | import com.android.tonyvu.sc.demo.model.CartItem;
17 | import com.android.tonyvu.sc.model.Cart;
18 | import com.android.tonyvu.sc.util.CartHelper;
19 |
20 | public class CartItemAdapter extends BaseAdapter {
21 | private static final String TAG = "CartItemAdapter";
22 |
23 | private List cartItems = Collections.emptyList();
24 |
25 | private final Context context;
26 |
27 | public CartItemAdapter(Context context) {
28 | this.context = context;
29 | }
30 |
31 | public void updateCartItems(List cartItems) {
32 | this.cartItems = cartItems;
33 | notifyDataSetChanged();
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return cartItems.size();
39 | }
40 |
41 | @Override
42 | public CartItem getItem(int position) {
43 | return cartItems.get(position);
44 | }
45 |
46 | @Override
47 | public long getItemId(int position) {
48 | return position;
49 | }
50 |
51 | @Override
52 | public View getView(final int position, View convertView, ViewGroup parent) {
53 | TextView tvName;
54 | TextView tvUnitPrice;
55 | TextView tvQuantity;
56 | TextView tvPrice;
57 | if (convertView == null) {
58 | convertView = LayoutInflater.from(context)
59 | .inflate(R.layout.adapter_cart_item, parent, false);
60 | tvName = (TextView) convertView.findViewById(R.id.tvCartItemName);
61 | tvUnitPrice = (TextView) convertView.findViewById(R.id.tvCartItemUnitPrice);
62 | tvQuantity = (TextView) convertView.findViewById(R.id.tvCartItemQuantity);
63 | tvPrice = (TextView) convertView.findViewById(R.id.tvCartItemPrice);
64 | convertView.setTag(new ViewHolder(tvName, tvUnitPrice, tvQuantity, tvPrice));
65 | } else {
66 | ViewHolder viewHolder = (ViewHolder) convertView.getTag();
67 | tvName = viewHolder.tvCartItemName;
68 | tvUnitPrice = viewHolder.tvCartItemUnitPrice;
69 | tvQuantity = viewHolder.tvCartItemQuantity;
70 | tvPrice = viewHolder.tvCartItemPrice;
71 | }
72 |
73 | final Cart cart = CartHelper.getCart();
74 | final CartItem cartItem = getItem(position);
75 | tvName.setText(cartItem.getProduct().getName());
76 | tvUnitPrice.setText(Constant.CURRENCY+String.valueOf(cartItem.getProduct().getPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
77 | tvQuantity.setText(String.valueOf(cartItem.getQuantity()));
78 | tvPrice.setText(Constant.CURRENCY+String.valueOf(cart.getCost(cartItem.getProduct()).setScale(2, BigDecimal.ROUND_HALF_UP)));
79 | return convertView;
80 | }
81 |
82 | private static class ViewHolder {
83 | public final TextView tvCartItemName;
84 | public final TextView tvCartItemUnitPrice;
85 | public final TextView tvCartItemQuantity;
86 | public final TextView tvCartItemPrice;
87 |
88 | public ViewHolder(TextView tvCartItemName, TextView tvCartItemUnitPrice, TextView tvCartItemQuantity, TextView tvCartItemPrice) {
89 | this.tvCartItemName = tvCartItemName;
90 | this.tvCartItemUnitPrice = tvCartItemUnitPrice;
91 | this.tvCartItemQuantity = tvCartItemQuantity;
92 | this.tvCartItemPrice = tvCartItemPrice;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/adapter/ProductAdapter.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo.adapter;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import android.content.Context;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.BaseAdapter;
13 | import android.widget.ImageView;
14 | import android.widget.TextView;
15 |
16 | import com.android.tonyvu.sc.demo.R;
17 | import com.android.tonyvu.sc.demo.constant.Constant;
18 | import com.android.tonyvu.sc.demo.model.Product;
19 |
20 | public class ProductAdapter extends BaseAdapter {
21 | private static final String TAG = "ProductAdapter";
22 |
23 | private List products = new ArrayList();
24 |
25 | private final Context context;
26 |
27 | public ProductAdapter(Context context) {
28 | this.context = context;
29 | }
30 |
31 | public void updateProducts(List products) {
32 | this.products.addAll(products);
33 | notifyDataSetChanged();
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return products.size();
39 | }
40 |
41 | @Override
42 | public Product getItem(int position) {
43 | return products.get(position);
44 | }
45 |
46 | @Override
47 | public long getItemId(int position) {
48 | return position;
49 | }
50 |
51 | @Override
52 | public View getView(int position, View convertView, ViewGroup parent) {
53 | TextView tvName;
54 | TextView tvPrice;
55 | ImageView ivImage;
56 | if (convertView == null) {
57 | convertView = LayoutInflater.from(context)
58 | .inflate(R.layout.adapter_product, parent, false);
59 | tvName = (TextView) convertView.findViewById(R.id.tvProductName);
60 | tvPrice = (TextView) convertView.findViewById(R.id.tvProductPrice);
61 | ivImage = (ImageView) convertView.findViewById(R.id.ivProductImage);
62 | convertView.setTag(new ViewHolder(tvName, tvPrice, ivImage));
63 | } else {
64 | ViewHolder viewHolder = (ViewHolder) convertView.getTag();
65 | tvName = viewHolder.tvProductName;
66 | tvPrice = viewHolder.tvProductPrice;
67 | ivImage = viewHolder.ivProductImage;
68 | }
69 |
70 | final Product product = getItem(position);
71 | tvName.setText(product.getName());
72 | tvPrice.setText(Constant.CURRENCY+String.valueOf(product.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP)));
73 | Log.d(TAG, "Context package name: " + context.getPackageName());
74 | ivImage.setImageResource(context.getResources().getIdentifier(
75 | product.getImageName(), "drawable", context.getPackageName()));
76 | // bView.setOnClickListener(new OnClickListener() {
77 | // @Override
78 | // public void onClick(View v) {
79 | // Intent intent = new Intent(context, ProductActivity.class);
80 | // Bundle bundle = new Bundle();
81 | // bundle.putSerializable("product", product);
82 | // Log.d(TAG, "This product hashCode: " + product.hashCode());
83 | // intent.putExtras(bundle);
84 | // context.startActivity(intent);
85 | // }
86 | // });
87 |
88 | return convertView;
89 | }
90 |
91 | private static class ViewHolder {
92 | public final TextView tvProductName;
93 | public final TextView tvProductPrice;
94 | public final ImageView ivProductImage;
95 |
96 | public ViewHolder(TextView tvProductName, TextView tvProductPrice, ImageView ivProductImage) {
97 | this.tvProductName = tvProductName;
98 | this.tvProductPrice = tvProductPrice;
99 | this.ivProductImage = ivProductImage;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/constant/Constant.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo.constant;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import com.android.tonyvu.sc.demo.model.Product;
8 |
9 | public final class Constant {
10 | public static final List QUANTITY_LIST = new ArrayList();
11 |
12 | static {
13 | for (int i = 1; i < 11; i++) QUANTITY_LIST.add(i);
14 | }
15 |
16 | public static final Product PRODUCT1 = new Product(1, "Samsung Galaxy S6", BigDecimal.valueOf(199.996), "Worldly looks and top-notch specs make the impressive, metal Samsung Galaxy S6 the Android phone to beat for 2015", "samsung_galaxy_s6");
17 | public static final Product PRODUCT2 = new Product(2, "HTC One M8", BigDecimal.valueOf(449.9947), "Excellent overall phone. Beautifull, battery life more than 20 hours daily and great customization in any way. 100% configuration on any aspect", "htc_one_m8");
18 | public static final Product PRODUCT3 = new Product(3, "Xiaomi Mi3", BigDecimal.valueOf(319.998140), "Xiaomi's Mi 3 is a showcase of how Chinese phonemakers can create quality hardware without breaking the bank. If you don't need 4G LTE, and you can get hold of it, this is one of the best smartphones you can buy in its price range.", "xiaomi_mi3");
19 |
20 | public static final List PRODUCT_LIST = new ArrayList();
21 |
22 | static {
23 | PRODUCT_LIST.add(PRODUCT1);
24 | PRODUCT_LIST.add(PRODUCT2);
25 | PRODUCT_LIST.add(PRODUCT3);
26 | }
27 |
28 | public static final String CURRENCY = "$";
29 | }
30 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/model/CartItem.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo.model;
2 |
3 | public class CartItem {
4 | private Product product;
5 | private int quantity;
6 |
7 | public int getQuantity() {
8 | return quantity;
9 | }
10 |
11 | public void setQuantity(int quantity) {
12 | this.quantity = quantity;
13 | }
14 |
15 | public Product getProduct() {
16 | return product;
17 | }
18 |
19 | public void setProduct(Product product) {
20 | this.product = product;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/android/tonyvu/sc/demo/model/Product.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.demo.model;
2 |
3 | import java.io.Serializable;
4 | import java.math.BigDecimal;
5 |
6 | import com.android.tonyvu.sc.model.Saleable;
7 |
8 | public class Product implements Saleable, Serializable {
9 | private static final long serialVersionUID = -4073256626483275668L;
10 |
11 | private int pId;
12 | private String pName;
13 | private BigDecimal pPrice;
14 | private String pDescription;
15 | private String pImageName;
16 |
17 | public Product() {
18 | super();
19 | }
20 |
21 | public Product(int pId, String pName, BigDecimal pPrice, String pDescription, String pImageName) {
22 | setId(pId);
23 | setName(pName);
24 | setPrice(pPrice);
25 | setDescription(pDescription);
26 | setImageName(pImageName);
27 | }
28 |
29 | @Override
30 | public boolean equals(Object o) {
31 | if (o == null) return false;
32 | if (!(o instanceof Product)) return false;
33 |
34 | return (this.pId == ((Product) o).getId());
35 | }
36 |
37 | public int hashCode() {
38 | final int prime = 31;
39 | int hash = 1;
40 | hash = hash * prime + pId;
41 | hash = hash * prime + (pName == null ? 0 : pName.hashCode());
42 | hash = hash * prime + (pPrice == null ? 0 : pPrice.hashCode());
43 | hash = hash * prime + (pDescription == null ? 0 : pDescription.hashCode());
44 |
45 | return hash;
46 | }
47 |
48 |
49 | public int getId() {
50 | return pId;
51 | }
52 |
53 | public void setId(int id) {
54 | this.pId = id;
55 | }
56 |
57 | @Override
58 | public BigDecimal getPrice() {
59 | return pPrice;
60 | }
61 |
62 | @Override
63 | public String getName() {
64 | return pName;
65 | }
66 |
67 | public void setPrice(BigDecimal price) {
68 | this.pPrice = price;
69 | }
70 |
71 | public void setName(String name) {
72 | this.pName = name;
73 | }
74 |
75 | public String getDescription() {
76 | return pDescription;
77 | }
78 |
79 | public void setDescription(String pDescription) {
80 | this.pDescription = pDescription;
81 | }
82 |
83 | public String getImageName() {
84 | return pImageName;
85 | }
86 |
87 | public void setImageName(String imageName) {
88 | this.pImageName = imageName;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/htc_one_m8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/drawable/htc_one_m8.jpg
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/samsung_galaxy_s6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/drawable/samsung_galaxy_s6.jpg
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/xiaomi_mi3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/drawable/xiaomi_mi3.jpg
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_cart.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
23 |
24 |
30 |
31 |
40 |
41 |
48 |
49 |
57 |
58 |
59 |
66 |
67 |
77 |
78 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
21 |
22 |
35 |
36 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_product.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
22 |
23 |
34 |
35 |
42 |
43 |
51 |
52 |
59 |
60 |
66 |
67 |
72 |
73 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/adapter_cart_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
26 |
27 |
33 |
34 |
41 |
42 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/adapter_product.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/cart_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
32 |
33 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/cart_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
29 |
30 |
38 |
39 |
47 |
48 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/product_list_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
29 |
30 |
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/src/main/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/demo/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 | 64dp
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 | #008000
3 | #ff5500
4 | #0000FF
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 | 16sp
7 | 14sp
8 | 5dp
9 | 14sp
10 |
11 |
12 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Android-ShoppingCart-Demo
5 |
6 | Product List
7 | Shopping Cart
8 | Name
9 | Unit Price
10 | Quantity
11 | View
12 | Action
13 | Order
14 | Price
15 | Total Price
16 | Remove
17 | Clear Cart
18 | Shop
19 | Delete Item
20 | Are you sure you want to delete this item?
21 | Yes
22 | No
23 |
24 |
25 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonyvu2014/android-shoppingcart/889e180c540c99bcd7dc8846cdc94099ff30899c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 19 19:32:47 SGT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 8
9 | targetSdkVersion 23
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/java/com/android/tonyvu/sc/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.exception;
2 |
3 | /**
4 | * Throw this exception to indicate invalid operation on product which does not belong to a shopping cart
5 | */
6 | public class ProductNotFoundException extends RuntimeException {
7 | private static final long serialVersionUID = 43L;
8 |
9 | private static final String DEFAULT_MESSAGE = "Product is not found in the shopping cart.";
10 |
11 | public ProductNotFoundException() {
12 | super(DEFAULT_MESSAGE);
13 | }
14 |
15 | public ProductNotFoundException(String message) {
16 | super(message);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/library/src/main/java/com/android/tonyvu/sc/exception/QuantityOutOfRangeException.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.exception;
2 |
3 | /**
4 | * Throw this exception to indicate invalid quantity to be used on a shopping cart product.
5 | */
6 | public class QuantityOutOfRangeException extends RuntimeException {
7 | private static final long serialVersionUID = 44L;
8 |
9 | private static final String DEFAULT_MESSAGE = "Quantity is out of range";
10 |
11 | public QuantityOutOfRangeException() {
12 | super(DEFAULT_MESSAGE);
13 | }
14 |
15 | public QuantityOutOfRangeException(String message) {
16 | super(message);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/library/src/main/java/com/android/tonyvu/sc/model/Cart.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.model;
2 |
3 | import java.io.Serializable;
4 | import java.math.BigDecimal;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.Map.Entry;
8 | import java.util.Set;
9 |
10 | import com.android.tonyvu.sc.exception.ProductNotFoundException;
11 | import com.android.tonyvu.sc.exception.QuantityOutOfRangeException;
12 |
13 | /**
14 | * A representation of shopping cart.
15 | *
16 | * A shopping cart has a map of {@link Saleable} products to their corresponding quantities.
17 | */
18 | public class Cart implements Serializable {
19 | private static final long serialVersionUID = 42L;
20 |
21 | private Map cartItemMap = new HashMap();
22 | private BigDecimal totalPrice = BigDecimal.ZERO;
23 | private int totalQuantity = 0;
24 |
25 | /**
26 | * Add a quantity of a certain {@link Saleable} product to this shopping cart
27 | *
28 | * @param sellable the product will be added to this shopping cart
29 | * @param quantity the amount to be added
30 | */
31 | public void add(final Saleable sellable, int quantity) {
32 | if (cartItemMap.containsKey(sellable)) {
33 | cartItemMap.put(sellable, cartItemMap.get(sellable) + quantity);
34 | } else {
35 | cartItemMap.put(sellable, quantity);
36 | }
37 |
38 | totalPrice = totalPrice.add(sellable.getPrice().multiply(BigDecimal.valueOf(quantity)));
39 | totalQuantity += quantity;
40 | }
41 |
42 | /**
43 | * Set new quantity for a {@link Saleable} product in this shopping cart
44 | *
45 | * @param sellable the product which quantity will be updated
46 | * @param quantity the new quantity will be assigned for the product
47 | * @throws ProductNotFoundException if the product is not found in this shopping cart.
48 | * @throws QuantityOutOfRangeException if the quantity is negative
49 | */
50 | public void update(final Saleable sellable, int quantity) throws ProductNotFoundException, QuantityOutOfRangeException {
51 | if (!cartItemMap.containsKey(sellable)) throw new ProductNotFoundException();
52 | if (quantity < 0)
53 | throw new QuantityOutOfRangeException(quantity + " is not a valid quantity. It must be non-negative.");
54 |
55 | int productQuantity = cartItemMap.get(sellable);
56 | BigDecimal productPrice = sellable.getPrice().multiply(BigDecimal.valueOf(productQuantity));
57 |
58 | cartItemMap.put(sellable, quantity);
59 |
60 | totalQuantity = totalQuantity - productQuantity + quantity;
61 | totalPrice = totalPrice.subtract(productPrice).add(sellable.getPrice().multiply(BigDecimal.valueOf(quantity)));
62 | }
63 |
64 | /**
65 | * Remove a certain quantity of a {@link Saleable} product from this shopping cart
66 | *
67 | * @param sellable the product which will be removed
68 | * @param quantity the quantity of product which will be removed
69 | * @throws ProductNotFoundException if the product is not found in this shopping cart
70 | * @throws QuantityOutOfRangeException if the quantity is negative or more than the existing quantity of the product in this shopping cart
71 | */
72 | public void remove(final Saleable sellable, int quantity) throws ProductNotFoundException, QuantityOutOfRangeException {
73 | if (!cartItemMap.containsKey(sellable)) throw new ProductNotFoundException();
74 |
75 | int productQuantity = cartItemMap.get(sellable);
76 |
77 | if (quantity < 0 || quantity > productQuantity)
78 | throw new QuantityOutOfRangeException(quantity + " is not a valid quantity. It must be non-negative and less than the current quantity of the product in the shopping cart.");
79 |
80 | if (productQuantity == quantity) {
81 | cartItemMap.remove(sellable);
82 | } else {
83 | cartItemMap.put(sellable, productQuantity - quantity);
84 | }
85 |
86 | totalPrice = totalPrice.subtract(sellable.getPrice().multiply(BigDecimal.valueOf(quantity)));
87 | totalQuantity -= quantity;
88 | }
89 |
90 | /**
91 | * Remove a {@link Saleable} product from this shopping cart totally
92 | *
93 | * @param sellable the product to be removed
94 | * @throws ProductNotFoundException if the product is not found in this shopping cart
95 | */
96 | public void remove(final Saleable sellable) throws ProductNotFoundException {
97 | if (!cartItemMap.containsKey(sellable)) throw new ProductNotFoundException();
98 |
99 | int quantity = cartItemMap.get(sellable);
100 | cartItemMap.remove(sellable);
101 | totalPrice = totalPrice.subtract(sellable.getPrice().multiply(BigDecimal.valueOf(quantity)));
102 | totalQuantity -= quantity;
103 | }
104 |
105 | /**
106 | * Remove all products from this shopping cart
107 | */
108 | public void clear() {
109 | cartItemMap.clear();
110 | totalPrice = BigDecimal.ZERO;
111 | totalQuantity = 0;
112 | }
113 |
114 | /**
115 | * Get quantity of a {@link Saleable} product in this shopping cart
116 | *
117 | * @param sellable the product of interest which this method will return the quantity
118 | * @return The product quantity in this shopping cart
119 | * @throws ProductNotFoundException if the product is not found in this shopping cart
120 | */
121 | public int getQuantity(final Saleable sellable) throws ProductNotFoundException {
122 | if (!cartItemMap.containsKey(sellable)) throw new ProductNotFoundException();
123 | return cartItemMap.get(sellable);
124 | }
125 |
126 | /**
127 | * Get total cost of a {@link Saleable} product in this shopping cart
128 | *
129 | * @param sellable the product of interest which this method will return the total cost
130 | * @return Total cost of the product
131 | * @throws ProductNotFoundException if the product is not found in this shopping cart
132 | */
133 | public BigDecimal getCost(final Saleable sellable) throws ProductNotFoundException {
134 | if (!cartItemMap.containsKey(sellable)) throw new ProductNotFoundException();
135 | return sellable.getPrice().multiply(BigDecimal.valueOf(cartItemMap.get(sellable)));
136 | }
137 |
138 | /**
139 | * Get total price of all products in this shopping cart
140 | *
141 | * @return Total price of all products in this shopping cart
142 | */
143 | public BigDecimal getTotalPrice() {
144 | return totalPrice;
145 | }
146 |
147 | /**
148 | * Get total quantity of all products in this shopping cart
149 | *
150 | * @return Total quantity of all products in this shopping cart
151 | */
152 | public int getTotalQuantity() {
153 | return totalQuantity;
154 | }
155 |
156 | /**
157 | * Get set of products in this shopping cart
158 | *
159 | * @return Set of {@link Saleable} products in this shopping cart
160 | */
161 | public Set getProducts() {
162 | return cartItemMap.keySet();
163 | }
164 |
165 | /**
166 | * Get a map of products to their quantities in the shopping cart
167 | *
168 | * @return A map from product to its quantity in this shopping cart
169 | */
170 | public Map getItemWithQuantity() {
171 | Map cartItemMap = new HashMap();
172 | cartItemMap.putAll(this.cartItemMap);
173 | return cartItemMap;
174 | }
175 |
176 | @Override
177 | public String toString() {
178 | StringBuilder strBuilder = new StringBuilder();
179 | for (Entry entry : cartItemMap.entrySet()) {
180 | strBuilder.append(String.format("Product: %s, Unit Price: %f, Quantity: %d%n", entry.getKey().getName(), entry.getKey().getPrice(), entry.getValue()));
181 | }
182 | strBuilder.append(String.format("Total Quantity: %d, Total Price: %f", totalQuantity, totalPrice));
183 |
184 | return strBuilder.toString();
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/library/src/main/java/com/android/tonyvu/sc/model/Saleable.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.model;
2 |
3 | import java.math.BigDecimal;
4 |
5 | /**
6 | * Implements this interface for any product which can be added to shopping cart
7 | */
8 | public interface Saleable {
9 | BigDecimal getPrice();
10 |
11 | String getName();
12 | }
13 |
--------------------------------------------------------------------------------
/library/src/main/java/com/android/tonyvu/sc/util/CartHelper.java:
--------------------------------------------------------------------------------
1 | package com.android.tonyvu.sc.util;
2 |
3 | import com.android.tonyvu.sc.model.Cart;
4 |
5 | /**
6 | * A helper class to retrieve the static shopping cart. Call {@code getCart()} to retrieve the shopping cart before you perform any operation on the shopping cart.
7 | *
8 | * @author Tony
9 | */
10 | public class CartHelper {
11 | private static Cart cart = new Cart();
12 |
13 | /**
14 | * Retrieve the shopping cart. Call this before perform any manipulation on the shopping cart.
15 | *
16 | * @return the shopping cart
17 | */
18 | public static Cart getCart() {
19 | if (cart == null) {
20 | cart = new Cart();
21 | }
22 |
23 | return cart;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':library'
2 |
--------------------------------------------------------------------------------