Android-主頁實現 6種適配器的適配 & 搶購頁面實現—購物商場實戰項目02


不否認努力,繼續加油!

學習整理重點、盲區,筆記如下:乾乾巴巴,麻麻賴賴,一點都不圓潤……
源碼 已上傳至集哈:ShoppingMall.
https://github.com/SmileAlfred/ShoppingMall

day02

內容

1. 主頁面結構分析

  1. 佈局分析;
    除去 RadioButton 外,上半啦整體是一個 相對佈局
    title + RecyclerView + FloatButton;

  2. 其中 title 用線性佈局;利用 DrawableLeft 和 DrawableTop 設置兩文本;

  3. RecyclerView 需要對不同顯示,設置不同的 6 種適配器;
    在這裏插入圖片描述

  4. 初始化佈局和設置監聽
    需要使用 view 去實例化控件,不可以直接 findViewById();

    @Override
    public View initView() {
        View view = View.inflate(mContext, R.layout.fragment_home, null);
        rvHome = (RecyclerView) view.findViewById(R.id.rv_home);
        ib_top = (ImageView) view.findViewById(R.id.ib_top);
        tv_search_home = (TextView) view.findViewById(R.id.tv_search_home);
        tv_message_home = (TextView) view.findViewById(R.id.tv_message_home);
        //設置點擊事件
        initListener();
        return view;
    }
    

2. 請求主頁數據和解決數據

  1. 使用 OkHttpUtil s 請求網絡

    添加依賴:implementation 'com.github.xxl6097:okhttputils:2.4.1'
    添加聯網權限:
    
    private void getDataFromNet() {
        String url = Constants.HOME_URL;
        OkHttpUtils.get()
                .url(url)
                .build()
                .execute(new StringCallback() {
                    /**
                     * 當請求失敗的時候回調
                     */
                    @Override
                    public void onError(Call call, Exception e) {
                        Log.e(TAG, "首頁請求失敗==" + e.getMessage());
                    }
                    /**
                     * 當聯網成功的時候回調
                     */
                    @Override
                    public void onResponse(Call call, String s) {
                        Log.e(TAG, "首頁請求成功==" + s);
                        //解析數據
                        processData(s);
                    }
                });
    }
    
  2. 配置聯網路徑

    //這裏創建了一個常量類,其中的常量用靜態字符串表示;
    public class Constants {
        public static String BASE_URL = "http://192.168.0.9:8080/atguigu";
        /**
         * 主頁面的路徑
         */
        public static String HOME_URL  = BASE_URL+"/json/HOME_URL.json";
        /**
         * 圖片的基本路徑
         */
        public static String BASE_URL_IMAGE  = BASE_URL+"/img";
    }
    
  3. 使用 fastjson(By Alibaba) 解析數據

    添加依賴:implementation 'com.alibaba:fastjson:1.2.68'
    
    private void processData(String json) {
    	if (!TextUtils.isEmpty(json)) {
        	ResultBeanData resultBeanData = JSON.parseObject(json, ResultBeanData.class);
        	resultBean = resultBeanData.getResult();
        	Log.e(TAG, "解析成功==" + resultBean.getHot_info().get(0).getName());
        }
    }
    
  4. 生成 JeanBean
    使用插件 GsonFromat 生成 Bean 對象;

3. 主頁面適配器

  1. 選擇 RecyclerView,因爲其中可以使用不同種類的多種 adapter;首頁有六種不同的效果,分別是如下,廣告條,分類,ViewPager,秒殺欄,三欄的 RecyclerView,兩欄的 RecyclerView;
    在這裏插入圖片描述

  2. 六種類型的 ViewHolder ,設置類型,

    /**
     * 廣告條幅類型、頻道類型、活動類型、秒殺類型、推薦類型、熱賣;
     */
    public static final int BANNER = 0;
    public static final int CHANNEL = 1;
    public static final int ACT = 2;
    public static final int SECKILL = 3;
    public static final int RECOMMEND = 4;
    public static final int HOT = 5;
    /**
     * 當前類型
     */
    private int currentType = BANNER;
    
  3. 適配器代碼

    /**
     * 數據對象
     */
    private ResultBean resultBean;
    private Context mContext;
    private LayoutInflater mLayoutInflater;
    @Override
    public int getItemCount() {
        //以後做完後改成6,現在只實現橫幅廣告,暫時寫1 
        return 1;
    }
    @Override
    public int getItemViewType(int position) {
        switch (position) {
            case BANNER:
                currentType = BANNER;
                break;
            case CHANNEL:
                currentType = CHANNEL;
                break;
            case ACT:
                currentType = ACT;
                break;
            case SECKILL:
                currentType = SECKILL;
                break;
            case RECOMMEND:
                currentType = RECOMMEND;
                break;
            case HOT:
                currentType = HOT;
                break;
        }
        return currentType;
    }
    public HomeRecycleAdapter(Context mContext, ResultBean resultBean) {
        this.mContext = mContext;
        this.resultBean = resultBean;
        mLayoutInflater = LayoutInflater.from(mContext);
    }
    

4. 設置橫幅廣播的適配器

  1. 關聯使用 Banner 庫;
    實現效果:切換頁面像手風琴一樣的推動;
    在這裏插入圖片描述

  2. 設置適配器繼承自 RecyclerView.Adapter;

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == BANNER) {
            return new BannerViewHolder(mLayoutInflater.inflate(R.layout.banner_viewpager, null), mContext, resultBean);
        }
        return null;
    }
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == BANNER) {
            BannerViewHolder bannerViewHolder = (BannerViewHolder) holder;
            //設置數據Banner的數據
            bannerViewHolder.setData(resultBean.getBanner_info());
        }
    }
    /**
     * 設置適配器
     */
    class BannerViewHolder extends RecyclerView.ViewHolder {
        public Banner banner;
        public Context mContext;
        public ResultBean resultBean;
        public BannerViewHolder(View itemView, Context mContext, ResultBean resultBean) {
            super(itemView);
            banner = (Banner) itemView.findViewById(R.id.banner);
            this.mContext = mContext;
            this.resultBean = resultBean;
        }
        public void setData(final List<ResultBean.BannerInfoBean> banner_info) {
            setBannerData(banner_info);
        }
    }
    
  3. 使用 Banner 庫

    private void setBannerData(final List<ResultBean.BannerInfoBean> banner_info) {
        //設置循環指標點
        banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
        //如果想用自己項目的圖片加載,就自定義圖片加載框架
        List<String> imageUris = new ArrayList<>();
        for (int i = 0; i < resultBean.getBanner_info().size(); i++) {
            imageUris.add(resultBean.getBanner_info().get(i).getImage());
        }
        // 設置類似手風琴動畫
        banner.setBannerAnimation(Transformer.Accordion);
        //設置加載圖片
        banner.setImages(imageUris, new OnLoadImageListener() {
            @Override
            public void OnLoadImage(ImageView view, Object url) { 
                Glide.with(mContext).load(Constants.Base_URl_IMAGE + url).into(view);
            }
        });
        //設置點擊事件 
        banner.setOnBannerClickListener(new OnBannerClickListener() {
            @Override
            public void OnBannerClick(int position) {
            	Toast.makeText(mContext, "position==" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }
    
  4. 設置佈局管理者
    此時運行是不會有效果的,因爲沒有設置佈局管理者;GridLayoutManager manager = new GridLayoutManager(mContext, 1);

    首頁設置完適配器後,要及時添加如上佈局管理者,這裏選擇GridLayout 而不是選擇 RelativeLayout 和 LinearLayout;

5. 頻道適配器

  1. 設置適配器繼承自 BaseAdapter;
    實現效果:
    在這裏插入圖片描述

  2. 和 Banner 適配器類似

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == BANNER) {
            return new BannerViewHolder(mLayoutInflater.inflate(R.layout.banner_viewpager, null), mContext, resultBean);
        }else if (viewType == CHANNEL) { 
        	return new ChannelViewHolder(mLayoutInflater.inflate(R.layout.channel_item, null), mContext); 
        	}
        return null;
    }
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == BANNER) {
            BannerViewHolder bannerViewHolder = (BannerViewHolder) holder;
            //設置數據Banner的數據
            bannerViewHolder.setData(resultBean.getBanner_info());
        }else if (getItemViewType(position) == CHANNEL) { 
        	ChannelViewHolder channelViewHolder = (ChannelViewHolder) holder; 
        	channelViewHolder.setData(resultBean.getChannel_info());
    }
    /**
     * 設置適配器
     */
    class ChannelViewHolder extends RecyclerView.ViewHolder {
        public GridView gvChannel;
        public Context mContext;
        public ChannelViewHolder(View itemView, Context mContext) {
            super(itemView);
            gvChannel = (GridView) itemView.findViewById(R.id.gv_channel);
            this.mContext = mContext;
        }
        public void setData(final List<ResultBean.ChannelInfoBean> channel_info) {
            gvChannel.setAdapter(new ChannelAdapter(mContext, channel_info)); 
            //點擊事件 gvChannel.setOnItemClickListener(new
            AdapterView.OnItemClickListener() {
                @Override public void onItemClick (AdapterView < ? > parent, View view,int position,
                long id){
                    if (position <= 8) {
                        Toast.makeText(mContext, "position==" + position, Toast.LENGTH_SHORT).show();
                    }   
                }
            });
        }
    }
    
  3. 不同的是,這裏不用設置佈局管理者也可以顯示,原因應該是繼承的 adapter 的原因;奇怪不……不理解……

  4. 頻道適配器 ChannelAdapter

    public class ChannelAdapter extends BaseAdapter {
        private Context mContext;
        private List<ResultBean.ChannelInfoBean> channel_info;
        public ChannelAdapter(Context mContext, List<ResultBean.ChannelInfoBean> channel_info) {
            this.mContext = mContext;
            this.channel_info = channel_info;
        }
        @Override
        public int getCount() {
            return channel_info == null ? 0 : channel_info.size();
        }
        @Override
        public Object getItem(int position) {
            return channel_info.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holer;
            if (convertView == null) {
                convertView = View.inflate(mContext, R.layout.item_channel, null);
                holer = new ViewHolder(convertView);
                convertView.setTag(holer);
            } else {
                holer = (ViewHolder) convertView.getTag();
            }
            ResultBean.ChannelInfoBean channelInfoBean = channel_info.get(position);
            holer.tvChannel.setText(channelInfoBean.getChannel_name());
            Glide.with(mContext).load(Constants.Base_URl_IMAGE + channelInfoBean.getImage()).into(holer.ivChannel);
            return convertView;
        }
        static class ViewHolder {
            @Bind(R.id.iv_channel)
            ImageView ivChannel;
            @Bind(R.id.tv_channel)
            TextView tvChannel;
            ViewHolder(View view) {
                ButterKnife.bind(this, view);
            }
        }
    }
    
  5. 寫佈局文件;

6. 活動適配器

  1. 寫佈局,實現如下廣告條效果:在這裏插入圖片描述

  2. 設置適配器;這裏用到的是 PagerAdapter;

    class ActViewHolder extends RecyclerView.ViewHolder {
        public ViewPager actViewPager;
        public Context mContext;
        public ActViewHolder(View itemView, Context mContext) {
            super(itemView);
            actViewPager = (ViewPager) itemView.findViewById(R.id.act_viewpager);
            this.mContext = mContext;
        }
        public void setData(final List<ResultBean.ActInfoBean> data) {
            //設置每個頁面的間距 
            actViewPager.setPageMargin(20); //>=3 
            actViewPager.setOffscreenPageLimit(3);
            //第三方庫實現頁面切換的不同動畫:implementation 'com.zhy:magic-viewpager:1.0.1'
            actViewPager.setPageTransformer(true, new AlphaPageTransformer(new ScaleInTransformer()));
            actViewPager.setAdapter(new PagerAdapter() {
                @Override
                public int getCount() {
                    return data.size();
                }
                @Override
                public boolean isViewFromObject(View view, Object object) {
                    return view == object;
                }
                @Override
                public Object instantiateItem(ViewGroup container, int position) {
                    ImageView view = new ImageView(mContext);
                    view.setScaleType(ImageView.ScaleType.FIT_XY);
                    //綁定數據 
                    Glide.with(mContext).load(Constants.Base_URl_IMAGE + data.get(position).getIcon_url()).into(view)
                    container.addView(view);
                    return view;
                }
                @Override
                public void destroyItem(ViewGroup container, int position, Object object) {
                    container.removeView((View) object);
                }
            });
            //點擊事件 
            actViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {
                }
                @Override
                public void onPageSelected(int position) {
                    Toast.makeText(mContext, "position:" + position, Toast.LENGTH_SHORT).show();
                }
                @Override
                public void onPageScrollStateChanged(int state) {
                }
            });
        }
    }
    

7. 秒殺適配器

  1. 寫佈局,實現如下效果:上邊時橫向的linear layout;下面是橫滑的 RecyclerView;
    在這裏插入圖片描述

  2. 設置 SeckillViewHolder ;

    class SeckillViewHolder extends RecyclerView.ViewHolder {
    	//與上述類似,省略相同方法;……
    	public void setData(final ResultBeanData.ResultBean.SeckillInfoBean seckill_info) {
    	    //1.設置數據:文本和RecyclerView的數據
    	    adapter = new SeckillRecyclerViewAdapter(mContext, seckill_info.getList());
    	    rv_seckill.setAdapter(adapter);
    	    //2.設置佈局管理器
    	    rv_seckill.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
    	    //3.設置item的點擊事件
    	    adapter.setOnSeckillRecyclerView(new SeckillRecyclerViewAdapter.OnSeckillRecyclerView() {
    	        @Override
    	        public void onItemClick(int position) {
    	            Toast.makeText(mContext, "秒殺" + position, Toast.LENGTH_SHORT).show();
    	        }
    	    });
    	    //4.秒殺倒計時 -毫秒
    	    dt = Integer.valueOf(seckill_info.getEnd_time()) - Integer.valueOf(seckill_info.getStart_time());
    	    handler.sendEmptyMessageDelayed(0, 1000);
    	}
    	//5.設置倒計時
    	private Handler handler = new Handler() {
    	    @Override
    	    public void handleMessage(Message msg) {
    	        super.handleMessage(msg);
    	        dt = dt - 1000;
    	        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
    	        String time = formatter.format(new Date(dt));
    	        tv_time_seckill.setText(time);
    	        handler.removeMessages(0);
    	        handler.sendEmptyMessageDelayed(0, 1000);
    	        if (dt <= 0) {
    	            //把消息移除
    	            handler.removeCallbacksAndMessages(null);
    	        }
    	    }
    	};
    }
    
  3. 設置橫滑 RecyclerView 的適配器和監聽器;

    public class SeckillRecyclerViewAdapter extends RecyclerView.Adapter<SeckillRecyclerViewAdapter.ViewHodler> {
        private final List<ResultBeanData.ResultBean.SeckillInfoBean.ListBean> list;
        private final Context mContext;
    
        public SeckillRecyclerViewAdapter(Context mContext, List<ResultBeanData.ResultBean.SeckillInfoBean.ListBean> list) {
            this.list = list;
            this.mContext = mContext;
        }
    
        @Override
        public ViewHodler onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = View.inflate(mContext, R.layout.item_seckill, null);
            return new ViewHodler(itemView);
        }
    
        @Override
        public void onBindViewHolder(ViewHodler holder, int position) {
            //1.根據位置得到對應的數據
            ResultBeanData.ResultBean.SeckillInfoBean.ListBean listBean = list.get(position);
            //2.綁定數據
            Glide.with(mContext).load(Constants.BASE_URL_IMAGE + listBean.getFigure()).into(holder.iv_figure);
            holder.tv_cover_price.setText(listBean.getCover_price());
            holder.tv_origin_price.setText(listBean.getOrigin_price());
        }
    
        @Override
        public int getItemCount() {
            return list.size();
        }
    
        class ViewHodler extends RecyclerView.ViewHolder {
            private ImageView iv_figure;
            private TextView tv_cover_price;
            private TextView tv_origin_price;
    
            public ViewHodler(View itemView) {
                super(itemView);
                iv_figure = (ImageView) itemView.findViewById(R.id.iv_figure);
                tv_cover_price = (TextView) itemView.findViewById(R.id.tv_cover_price);
                tv_origin_price = (TextView) itemView.findViewById(R.id.tv_origin_price);
                tv_origin_price.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG );//給原價 TextView 添加橫滑線
    
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(mContext, "秒殺="+getLayoutPosition(), Toast.LENGTH_SHORT).show();
                        if (onSeckillRecyclerView != null) {
                            onSeckillRecyclerView.onItemClick(getLayoutPosition());
                        }
                    }
                });
            }
        }
    
        /**
         * 監聽器
         */
        public interface OnSeckillRecyclerView {
            //當某條被點擊的時候回調
            public void onItemClick(int position);
        }
    
        private OnSeckillRecyclerView onSeckillRecyclerView;
        //設置item的監聽
        public void setOnSeckillRecyclerView(OnSeckillRecyclerView onSeckillRecyclerView) {
            this.onSeckillRecyclerView = onSeckillRecyclerView;
        }
    }
    

8. 推薦適配器

  1. 寫佈局,實現如下效果:上邊時橫向的 LinearLayout;下面是三列形式的 GridView;

    <GridView
        android:id="@+id/gv_recommend"
        android:layout_width="match_parent"
        android:layout_height="380dp"
        android:numColumns="3"/>
    

    在這裏插入圖片描述

  2. 設置 RecommendViewHolder;

  3. 設置適配器和監聽器;

9. 熱賣適配器

  1. 寫佈局,實現如下效果:上邊時橫向的 LinearLayout;下面是兩列形式的 GridView;
    在這裏插入圖片描述
  2. 設置 RecommendViewHolder;
  3. 設置適配器和監聽器;

10. 設置監聽 RecyclerView 的位置

  1. 隱藏和顯示回到頂部按鈕

    實現目的:當頁面滑動不在首頁時,右下角的 float button 顯示,點擊後回到頂部,而後隱藏;

    //HomeFragment.java 中 processData();
    adapter = new HomeFragmentAdapter(mContext, resultBean);
    rvHome.setAdapter(adapter);
    GridLayoutManager manager = new GridLayoutManager(mContext, 1);
    //設置跨度大小監聽
    manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            if (position <= 3) {
                ib_top.setVisibility(View.GONE);
            } else {
                ib_top.setVisibility(View.VISIBLE);
            }
            //只能返回1
            return 1;
        }
    });
    //設置佈局管理者
    rvHome.setLayoutManager(manager);
    
  2. 實現點擊回到頂部的監聽方法;

    ib_top.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            rvHome.scrollToPosition(0);
        }
    

11. 商品信息列表類 GoodsInfoActivity

  1. 商品信息列表類頁面實現分析
    佈局分成三部分:
    1:標題欄
    2:分割線
    3:幀布居
    a: 線性佈局;裏面用 ScrollViewContainer 嵌套兩個 ScrollView
    b: 線性佈局;客服聯繫,收藏,購物車等
    c: 更多;分享, 搜索,首頁等

  2. 寫佈局 activity_goods_info.xml;

  3. 佈局的實例化和設置點擊事件;

  4. 商品詳情頁面的數據傳遞和接收;

    傳遞對象時,要將其序列化;

    //傳遞對象
    Intent intent = new Intent(mContext, GoodsInfoActivity.class);
    intent.putExtra(GOODS_BEAN,goodsBean);
    mContext.startActivity(intent);
    //取出intent 
    Intent intent = getIntent(); 
    goods_bean = (GoodsBean) intent.getSerializableExtra("goods_bean");
    
  5. 解析數據並設置商品詳情頁面數據

  6. 使用 WebView 加載設置 商品詳情 數據

盲區

  1. 聲明:本博客根據尚硅谷項目實戰: 硅谷商城.學習整理;
  2. 對於 okhttputils 一些封裝工具,用的不熟悉,尤其是在Json數據解析時間,接下來會深入學習,並會同步更新詳細筆記;
  3. 在設置 RadioButton 的監聽器時報錯,內容顯示 Butterknife 和監聽衝突,最後還是老老實實 findViewById(),解了,不過應該對 Butterknife 再研究一下;
  4. 設置適配器的時候,出現了 BaseAdapter 、 RecyclerView.Adapter 和 PagerAdapter;使用 RecyclerView.Adapter 時要寫佈局管理者;對於這些適配器還不瞭解;
  5. 對於加載商品詳情頁面時,對於其 json 數據的解析還是存在瑕疵;
  6. 加油!奧裏給!

其他實戰

商城

  1. day01
    第一節學習筆記:鏈接: 商城APP01—框架搭建.

  2. day02
    第二節學習筆記:鏈接: 商城APP02—主頁實現.

  3. day03
    第三節學習筆記:鏈接: 商城APP03—購物車實現.

新聞

Android項目實戰——新聞APP 學習筆記:鏈接: 新聞APP.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章