Shopping cart for Android App development actual project (with source code, super detailed must-see)

If you need the source code, please like, follow and leave a comment in the comment area~~~

1. Requirements description

The shopping cart of the e-commerce app is commonplace. You can know that there is a settlement line at the bottom of the shopping cart, and the rest of the shopping cart is mainly a list of products that have been added to the shopping cart. Then, the left side of each product is a small picture of the product, and the right side is the product name and price. , the first time you enter the shopping cart page should be empty, and it will increase as you add more things. And you can also see the shopping cart in other interfaces, for example, when a new product is added, the number will increase by one

2. Interface Design

The following controls are mainly used

linear layout

grid layout

relative layout

DatabaseSQLite

global memory

memory card file

Shared parameters SharedPreferences

 The effect is as follows

 

3. Key parts

1: About page jump

Because the shopping cart page allows jumping directly to the shopping mall page, and the shopping mall page also allows jumping to the shopping cart page, so if the user jumps back and forth between these two pages, and then presses the return key, it turns out that it is also here when returning The reason for the problem when jumping between two pages is that every time an activity page is started, a new activity is added to the activity stack, and when returning to the stack, the activities have to be exited one by one.

2: Caching of product images

Usually, the product images are provided by the back-end server. When the app opens the page, it downloads the required product images from the server. However, multiple pages of the shopping cart module will display product images. If you request images from the server every time, it is obviously very time-consuming and expensive. Wandering, so the App will cache commonly used pictures, and once the pictures are successfully downloaded from the server, the picture files will be saved on the phone's storage card. Then next time the interface needs to load a product picture, first search for the picture from the memory card, if found, read it, if not found, go to the server to download

4. Part of the source code

ShoppingDetailActivity

package com.example.chapter06;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter06.bean.GoodsInfo;
import com.example.chapter06.database.CartDBHelper;
import com.example.chapter06.database.GoodsDBHelper;
import com.example.chapter06.util.ToastUtil;

@SuppressLint("SetTextI18n")
public class ShoppingDetailActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_title;
    private TextView tv_count;
    private TextView tv_goods_price;
    private TextView tv_goods_desc;
    private ImageView iv_goods_pic;
    private long mGoodsId; // 当前商品的商品编号
    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shopping_detail);
        tv_title = findViewById(R.id.tv_title);
        tv_count = findViewById(R.id.tv_count);
        tv_goods_price = findViewById(R.id.tv_goods_price);
        tv_goods_desc = findViewById(R.id.tv_goods_desc);
        iv_goods_pic = findViewById(R.id.iv_goods_pic);
        findViewById(R.id.iv_back).setOnClickListener(this);
        findViewById(R.id.iv_cart).setOnClickListener(this);
        findViewById(R.id.btn_add_cart).setOnClickListener(this);
        tv_count.setText("" + MainApplication.goodsCount);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.iv_back) { // 点击了返回图标
            finish(); // 关闭当前页面
        } else if (v.getId() == R.id.iv_cart) { // 点击了购物车图标
            Intent intent = new Intent(this, ShoppingCartActivity.class);
            startActivity(intent); // 跳转到购物车页面
        } else if (v.getId() == R.id.btn_add_cart) { // 点击了“添加”按钮
            addToCart(mGoodsId); // 把该商品添加到购物车
        }
    }

    // 把指定编号的商品添加到购物车
    private void addToCart(long goods_id) {
        MainApplication.goodsCount++;
        tv_count.setText("" + MainApplication.goodsCount);
        mCartHelper.save(goods_id); // 把该商品填入购物车数据库
        ToastUtil.show(this, "成功添加至购物车");
    }

    @Override
    protected void onResume() {
        super.onResume();
        // 获取商品数据库的帮助器对象
        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
        mGoodsHelper.openReadLink(); // 打开商品数据库的读连接
        // 获取购物车数据库的帮助器对象
        mCartHelper = CartDBHelper.getInstance(this, 1);
        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接
        showDetail(); // 展示商品详情
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接
        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接
    }

    private void showDetail() {
        // 获取上一个页面传来的商品编号
        mGoodsId = getIntent().getLongExtra("goods_id", 0L);
        if (mGoodsId > 0) {
            // 根据商品编号查询商品数据库中的商品记录
            GoodsInfo info = mGoodsHelper.queryById(mGoodsId);
            tv_title.setText(info.name); // 设置商品名称
            tv_goods_desc.setText(info.desc); // 设置商品描述
            tv_goods_price.setText("" + (int)info.price); // 设置商品价格
            iv_goods_pic.setImageURI(Uri.parse(info.pic_path)); // 设置商品图片
        }
    }

}

ShoppingChannelActivity类

package com.example.chapter06;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter06.bean.GoodsInfo;
import com.example.chapter06.database.CartDBHelper;
import com.example.chapter06.database.GoodsDBHelper;
import com.example.chapter06.util.ToastUtil;

import java.util.ArrayList;
import java.util.List;

@SuppressLint("SetTextI18n")
public class ShoppingChannelActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_count;
    private GridLayout gl_channel; // 声明一个商品频道的网格布局对象
    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shopping_channel);
        TextView tv_title = findViewById(R.id.tv_title);
        tv_title.setText("手机商场");
        tv_count = findViewById(R.id.tv_count);
        gl_channel = findViewById(R.id.gl_channel);
        findViewById(R.id.iv_back).setOnClickListener(this);
        findViewById(R.id.iv_cart).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.iv_back) { // 点击了返回图标
            finish(); // 关闭当前页面
        } else if (v.getId() == R.id.iv_cart) { // 点击了购物车图标
            // 从商场页面跳到购物车页面
            Intent intent = new Intent(this, ShoppingCartActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志
            startActivity(intent); // 跳转到购物车页面
        }
    }

    // 把指定编号的商品添加到购物车
    private void addToCart(long goods_id, String goods_name) {
        MainApplication.goodsCount++;
        tv_count.setText("" + MainApplication.goodsCount);
        mCartHelper.save(goods_id); // 把该商品填入购物车数据库
        ToastUtil.show(this, "已添加一部" + goods_name + "到购物车");
    }

    @Override
    protected void onResume() {
        super.onResume();
        tv_count.setText("" + MainApplication.goodsCount);
        // 获取商品数据库的帮助器对象
        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
        mGoodsHelper.openReadLink(); // 打开商品数据库的读连接
        // 获取购物车数据库的帮助器对象
        mCartHelper = CartDBHelper.getInstance(this, 1);
        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接
        showGoods(); // 展示商品列表
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接
        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接
    }

    private void showGoods() {
        gl_channel.removeAllViews(); // 移除下面的所有子视图
        // 查询商品数据库中的所有商品记录
        List<GoodsInfo> goodsArray = mGoodsHelper.query("1=1");
        for (final GoodsInfo info : goodsArray) {
            // 获取布局文件item_goods.xml的根视图
            View view = LayoutInflater.from(this).inflate(R.layout.item_goods, null);
            ImageView iv_thumb = view.findViewById(R.id.iv_thumb);
            TextView tv_name = view.findViewById(R.id.tv_name);
            TextView tv_price = view.findViewById(R.id.tv_price);
            Button btn_add = view.findViewById(R.id.btn_add);
            tv_name.setText(info.name); // 设置商品名称
            iv_thumb.setImageURI(Uri.parse(info.pic_path)); // 设置商品图片
            iv_thumb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(ShoppingChannelActivity.this, ShoppingDetailActivity.class);
                    intent.putExtra("goods_id", info.rowid);
                    startActivity(intent); // 跳到商品详情页面
                }
            });
            tv_price.setText("" + (int)info.price); // 设置商品价格
            btn_add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    addToCart(info.rowid, info.name); // 添加到购物车
                }
            });
            gl_channel.addView(view); // 把商品视图添加到网格布局
        }
    }

}

ShoppingCartActivity类

package com.example.chapter06;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter06.bean.CartInfo;
import com.example.chapter06.bean.GoodsInfo;
import com.example.chapter06.database.CartDBHelper;
import com.example.chapter06.database.GoodsDBHelper;
import com.example.chapter06.util.FileUtil;
import com.example.chapter06.util.SharedUtil;
import com.example.chapter06.util.ToastUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@SuppressLint("SetTextI18n")
public class ShoppingCartActivity extends AppCompatActivity implements View.OnClickListener {
    private final static String TAG = "ShoppingCartActivity";
    private TextView tv_count;
    private TextView tv_total_price;
    private LinearLayout ll_content;
    private LinearLayout ll_cart; // 声明一个购物车列表的线性布局对象
    private LinearLayout ll_empty;
    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象
    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shopping_cart);
        TextView tv_title = findViewById(R.id.tv_title);
        tv_title.setText("购物车");
        tv_count = findViewById(R.id.tv_count);
        tv_total_price = findViewById(R.id.tv_total_price);
        ll_content = findViewById(R.id.ll_content);
        ll_cart = findViewById(R.id.ll_cart);
        ll_empty = findViewById(R.id.ll_empty);
        findViewById(R.id.iv_back).setOnClickListener(this);
        findViewById(R.id.btn_shopping_channel).setOnClickListener(this);
        findViewById(R.id.btn_clear).setOnClickListener(this);
        findViewById(R.id.btn_settle).setOnClickListener(this);
    }

    // 显示购物车图标中的商品数量
    private void showCount() {
        tv_count.setText("" + MainApplication.goodsCount);
        if (MainApplication.goodsCount == 0) {
            ll_content.setVisibility(View.GONE);
            ll_cart.removeAllViews(); // 移除下面的所有子视图
            mGoodsMap.clear();
            ll_empty.setVisibility(View.VISIBLE);
        } else {
            ll_content.setVisibility(View.VISIBLE);
            ll_empty.setVisibility(View.GONE);
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.iv_back) { // 点击了返回图标
            finish(); // 关闭当前页面
        } else if (v.getId() == R.id.btn_shopping_channel) { // 点击了“商场”按钮
            // 从购物车页面跳到商场页面
            Intent intent = new Intent(this, ShoppingChannelActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志
            startActivity(intent); // 跳转到手机商场页面
        } else if (v.getId() == R.id.btn_clear) { // 点击了“清空”按钮
            mCartHelper.deleteAll(); // 清空购物车数据库
            MainApplication.goodsCount = 0;
            showCount(); // 显示最新的商品数量
            ToastUtil.show(this, "购物车已清空");
        } else if (v.getId() == R.id.btn_settle) { // 点击了“结算”按钮
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("结算商品");
            builder.setMessage("客官抱歉,支付功能尚未开通,请下次再来");
            builder.setPositiveButton("我知道了", null);
            builder.create().show(); // 显示提醒对话框
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        showCount(); // 显示购物车的商品数量
        // 获取商品数据库的帮助器对象
        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);
        mGoodsHelper.openWriteLink(); // 打开商品数据库的写连接
        // 获取购物车数据库的帮助器对象
        mCartHelper = CartDBHelper.getInstance(this, 1);
        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接
        downloadGoods(); // 模拟从网络下载商品图片
        showCart(); // 展示购物车中的商品列表
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接
        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接
    }

    // 声明一个购物车中的商品信息列表
    private List<CartInfo> mCartArray = new ArrayList<CartInfo>();
    // 声明一个根据商品编号查找商品信息的映射
    private HashMap<Long, GoodsInfo> mGoodsMap = new HashMap<Long, GoodsInfo>();

    private void deleteGoods(CartInfo info) {
        MainApplication.goodsCount -= info.count;
        // 从购物车的数据库中删除商品
        mCartHelper.delete("goods_id=" + info.goods_id);
        // 从购物车的列表中删除商品
        for (int i = 0; i < mCartArray.size(); i++) {
            if (info.goods_id == mCartArray.get(i).goods_id) {
                mCartArray.remove(i);
                break;
            }
        }
        showCount(); // 显示最新的商品数量
        ToastUtil.show(this, "已从购物车删除" + mGoodsMap.get(info.goods_id).name);
        mGoodsMap.remove(info.goods_id);
        refreshTotalPrice(); // 刷新购物车中所有商品的总金额
    }

    // 展示购物车中的商品列表
    private void showCart() {
        ll_cart.removeAllViews(); // 移除下面的所有子视图
        mCartArray = mCartHelper.query("1=1"); // 查询购物车数据库中所有的商品记录
        Log.d(TAG, "mCartArray.size()=" + mCartArray.size());
        if (mCartArray == null || mCartArray.size() <= 0) {
            return;
        }
        for (int i = 0; i < mCartArray.size(); i++) {
            final CartInfo info = mCartArray.get(i);
            // 根据商品编号查询商品数据库中的商品记录
            final GoodsInfo goods = mGoodsHelper.queryById(info.goods_id);
            Log.d(TAG, "name=" + goods.name + ",price=" + goods.price + ",desc=" + goods.desc);
            mGoodsMap.put(info.goods_id, goods);
            // 获取布局文件item_goods.xml的根视图
            View view = LayoutInflater.from(this).inflate(R.layout.item_cart, null);
            ImageView iv_thumb = view.findViewById(R.id.iv_thumb);
            TextView tv_name = view.findViewById(R.id.tv_name);
            TextView tv_desc = view.findViewById(R.id.tv_desc);
            TextView tv_count = view.findViewById(R.id.tv_count);
            TextView tv_price = view.findViewById(R.id.tv_price);
            TextView tv_sum = view.findViewById(R.id.tv_sum);
            // 给商品行添加点击事件。点击商品行跳到商品的详情页
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(ShoppingCartActivity.this, ShoppingDetailActivity.class);
                    intent.putExtra("goods_id", info.goods_id);
                    startActivity(intent); // 跳到商品详情页面
                }
            });
            // 给商品行添加长按事件。长按商品行就删除该商品
            view.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(final View v) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingCartActivity.this);
                    builder.setMessage("是否从购物车删除"+goods.name+"?");
                    builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ll_cart.removeView(v); // 移除当前视图
                            deleteGoods(info); // 删除该商品
                        }
                    });
                    builder.setNegativeButton("否", null);
                    builder.create().show(); // 显示提醒对话框
                    return true;
                }
            });
            iv_thumb.setImageURI(Uri.parse(goods.pic_path)); // 设置商品图片
            tv_name.setText(goods.name); // 设置商品名称
            tv_desc.setText(goods.desc); // 设置商品描述
            tv_count.setText("" + info.count); // 设置商品数量
            tv_price.setText("" + (int)goods.price); // 设置商品单价
            tv_sum.setText("" + (int)(info.count * goods.price)); // 设置商品总价
            ll_cart.addView(view); // 往购物车列表添加该商品行
        }
        refreshTotalPrice(); // 重新计算购物车中的商品总金额
    }

    // 重新计算购物车中的商品总金额
    private void refreshTotalPrice() {
        int total_price = 0;
        for (CartInfo info : mCartArray) {
            GoodsInfo goods = mGoodsMap.get(info.goods_id);
            total_price += goods.price * info.count;
        }
        tv_total_price.setText("" + total_price);
    }

    private String mFirst = "true"; // 是否首次打开
    // 模拟网络数据,初始化数据库中的商品信息
    private void downloadGoods() {
        // 获取共享参数保存的是否首次打开参数
        mFirst = SharedUtil.getIntance(this).readString("first", "true");
        // 获取当前App的私有下载路径
        String path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/";
        if (mFirst.equals("true")) { // 如果是首次打开
            ArrayList<GoodsInfo> goodsList = GoodsInfo.getDefaultList(); // 模拟网络图片下载
            for (int i = 0; i < goodsList.size(); i++) {
                GoodsInfo info = goodsList.get(i);
                long rowid = mGoodsHelper.insert(info); // 往商品数据库插入一条该商品的记录
                info.rowid = rowid;
                Bitmap pic = BitmapFactory.decodeResource(getResources(), info.pic);
                String pic_path = path + rowid + ".jpg";
                FileUtil.saveImage(pic_path, pic); // 往存储卡保存商品图片
                pic.recycle(); // 回收位图对象
                info.pic_path = pic_path;
                mGoodsHelper.update(info); // 更新商品数据库中该商品记录的图片路径
            }
        }
        // 把是否首次打开写入共享参数
        SharedUtil.getIntance(this).writeString("first", "false");
    }

}

The XML file is as follows

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/orange"
    android:orientation="vertical" >

    <include layout="@layout/title_shopping" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

            <LinearLayout
                android:id="@+id/ll_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:visibility="visible" >

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal" >

                    <TextView
                        android:layout_width="85dp"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:text="图片"
                        android:textColor="@color/black"
                        android:textSize="15sp" />

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="3"
                        android:gravity="center"
                        android:text="名称"
                        android:textColor="@color/black"
                        android:textSize="15sp" />

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:text="数量"
                        android:textColor="@color/black"
                        android:textSize="15sp" />

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:text="单价"
                        android:textColor="@color/black"
                        android:textSize="15sp" />

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:text="总价"
                        android:textColor="@color/black"
                        android:textSize="15sp" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/ll_cart"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:padding="0dp" >

                    <Button
                        android:id="@+id/btn_clear"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:text="清空"
                        android:textColor="@color/black"
                        android:textSize="17sp" />

                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center|right"
                        android:text="总金额:"
                        android:textColor="@color/black"
                        android:textSize="17sp" />

                    <TextView
                        android:id="@+id/tv_total_price"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginRight="10dp"
                        android:gravity="center|left"
                        android:textColor="@color/red"
                        android:textSize="25sp" />

                    <Button
                        android:id="@+id/btn_settle"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:text="结算"
                        android:textColor="@color/black"
                        android:textSize="17sp" />
                </LinearLayout>

            </LinearLayout>

            <LinearLayout
                android:id="@+id/ll_empty"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:visibility="gone" >

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="100dp"
                    android:layout_marginTop="100dp"
                    android:gravity="center"
                    android:text="哎呀,购物车空空如也,快去选购商品吧"
                    android:textColor="@color/black"
                    android:textSize="17sp" />

                <Button
                    android:id="@+id/btn_shopping_channel"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="逛逛手机商场"
                    android:textColor="@color/black"
                    android:textSize="17sp" />
            </LinearLayout>
        </RelativeLayout>
    </ScrollView>

</LinearLayout>
---------------
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/orange"
    android:orientation="vertical" >

    <include layout="@layout/title_shopping" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <GridLayout
            android:id="@+id/gl_channel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:columnCount="2" />
    </ScrollView>

</LinearLayout>
---------------
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/orange"
    android:orientation="vertical" >

    <include layout="@layout/title_shopping" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <ImageView
                android:id="@+id/iv_goods_pic"
                android:layout_width="match_parent"
                android:layout_height="350dp"
                android:scaleType="fitCenter" />

            <TextView
                android:id="@+id/tv_goods_price"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:textColor="@color/red"
                android:textSize="22sp" />

            <TextView
                android:id="@+id/tv_goods_desc"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:textColor="@color/black"
                android:textSize="15sp" />

            <Button
                android:id="@+id/btn_add_cart"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="加入购物车"
                android:textColor="@color/black"
                android:textSize="17sp" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

It's not easy to create and find it helpful, please like, follow and collect~~~

Guess you like

Origin blog.csdn.net/jiebaoshayebuhui/article/details/127738664