框架搭建
1.软件分包
com.example.shoppingmall
app
base
community
home
shoppingcart
type
user
utils
view
2. 启动页面布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<ImageView
android:id="@+id/app_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:src="@drawable/shoppingapp_logo" />
</RelativeLayout>
3. 启动页面代码
public class SplashActivity extends Activity
{
private static final String TAG = SplashActivity.class.getSimpleName();//"SplashActivity"
private boolean isStartMain = false;//是否进入主界面标志
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
//两秒后才执行到这里
//执行在主线程中
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
}, 2000);
}
/**
* 跳转到主页面,并且把当前页面关闭掉
*/
private void startMainActivity()
{
if (!isStartMain)
{
isStartMain = true;
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
//关闭当前页面
finish();
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.e(TAG, "onTouchEvent==Action" + event.getAction());
startMainActivity();
return super.onTouchEvent(event);
}
@Override
protected void onDestroy()
{
//把所有的消息和回调移除
handler.removeCallbacksAndMessages(null);
super.onDestroy();
}
}
主页面
1. 主页面布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical"
tools:context=".app.MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<RadioGroup
android:id="@+id/rg_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@drawable/home_bottom_parent_bg"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_home"
style="@style/MainButtonStyle"
android:drawableTop="@drawable/home_button_selector"
android:text="首页" />
<RadioButton
android:id="@+id/rb_type"
style="@style/MainButtonStyle"
android:drawableTop="@drawable/type_button_selector"
android:text="分类" />
<RadioButton
android:id="@+id/rb_community"
style="@style/MainButtonStyle"
android:drawableTop="@drawable/community_button_selector"
android:paddingTop="10dp"
android:text="发现" />
<RadioButton
android:id="@+id/rb_cart"
style="@style/MainButtonStyle"
android:drawableTop="@drawable/cart_button_selector"
android:text="购物车" />
<RadioButton
android:id="@+id/rb_user"
style="@style/MainButtonStyle"
android:drawableTop="@drawable/user_button_selector"
android:text="个人中心" />
</RadioGroup>
</LinearLayout>
2. 按钮样式
<style name="MainButtonStyle">
<!-- Customize your theme here. -->
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:button">@null</item>
<item name="android:textColor">@drawable/bottom_button_text_selector</item>
<item name="android:textSize">10sp</item>
<item name="android:gravity">center</item>
</style>
3. 使用 Butterknife 初始化布局
1. 配置快捷键
(1) 在 Setting->Plugins 中输入 butterknife 添加插件
(2) Android ButterKnife Aelezny ->点击安装
2. Module 里的 build.gradle(app) 里面添加
compile 'com.jakewharton:butterknife:7.0.1'
3. 在 MainActivity 中使用
public class MainActivity extends FragmentActivity
{
@Bind(R.id.frameLayout)
FrameLayout frameLayout;
@Bind(R.id.rb_home)
RadioButton rbHome;
@Bind(R.id.rb_type)
RadioButton rbType;
@Bind(R.id.rb_community)
RadioButton rbCommunity;
@Bind(R.id.rb_cart)
RadioButton rbCart;
@Bind(R.id.rb_user)
RadioButton rbUser;
@Bind(R.id.rg_main)
RadioGroup rgMain;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Butternif 和 Activity 绑定
ButterKnife.bind(this);
}
}
Fragment 的基类和各个子 Fragment
BaseFragment
/**
* @author: Hashub
* @WeChat: NGSHMVP
* @Date: 2018/8/24 16:53
* @function:基类Fragemnt
* 首页:HomeFragment
* 分类:UserFragment
* 发现:CommunityFragment
* 购物车:ShoppingCartFragment
* 用户中心:UserFragemnt
* 等都要继承该类
*/
public abstract class BaseFragment extends Fragment
{
protected Context mContext;
/**
* 当该类被系统创建的时候被回调
*
* @param savedInstanceState
*/
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mContext=getActivity();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
return initView();
}
/**
* 抽象类,由孩子实现,实现不同的效果
* @return
*/
public abstract View initView() ;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
initData();
}
/**
* 当子类需要联网请求数据的时候,可以重写该方法,在该方法中联网请求
*/
public void initData()
{
}
}
各个子 Fragment 创建
首页: HomeFragment
分类: TypeFragment
发现: CommunityFragment
购物车: ShoppingCartFragment
用户中心: UserFragemnt
以HomeFragment页面的内容为例如下
/**
* @author: Hashub
* @WeChat: NGSHMVP
* @Date: 2018/8/24 16:53
* @function:
*/
public class HomeFragment extends BaseFragment
{
@Override
public View initView()
{
return null;
}
}
初始化各个 Fragment 并且切换
1. 初始化各个 Fragment
/**
* 初始化Fragment
* 添加的时候要按照顺序
*/
private void initFragment()
{
fragments = new ArrayList<>();
fragments.add(new HomeFragment());
fragments.add(new TypeFragment());
fragments.add(new CommunityFragment());
fragments.add(new ShoppingCartFragment());
fragments.add(new UserFragment());
}
2. 各个 Fragment 的切换
/**
* 设置RadioGroup的监听
*/
private void initListener()
{
rgMain.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
switch (checkedId)
{
case R.id.rb_home://主页
position = 0;
break;
case R.id.rb_type://分类
position = 1;
break;
case R.id.rb_community://发现
position = 2;
break;
case R.id.rb_cart://购物车
position = 3;
break;
case R.id.rb_user://用户中心
position = 4;
break;
default:
position = 0;
break;
}
//根据位置取不同的Fragment
BaseFragment baseFragment = getFragment(position);
/**
* 第一参数:上次显示的Fragment
* 第二参数:当前正要显示的Fragment
*/
switchFragment(tempFragemnt, baseFragment);
}
});
}
/**
* 切换Fragment
*
* @param fromFragment
* @param nextFragment
*/
private void switchFragment(Fragment fromFragment, BaseFragment nextFragment)
{
if (tempFragemnt != nextFragment)
{
tempFragemnt = nextFragment;
if (nextFragment != null)
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
//判断nextFragment是否添加
if (!nextFragment.isAdded())
{
//隐藏当前Fragment
if (fromFragment != null)
{
transaction.hide(fromFragment);
}
//添加Fragment
transaction.add(R.id.frameLayout, nextFragment).commit();
}
else
{
//隐藏当前Fragment
if (fromFragment != null)
{
transaction.hide(fromFragment);
}
transaction.show(nextFragment).commit();
}
}
}
}
/**
* 根据位置取不同的Fragment
*
* @param position
* @return
*/
private BaseFragment getFragment(int position)
{
if (fragments != null && fragments.size() > 0)
{
BaseFragment baseFragment = fragments.get(position);
return baseFragment;
}
return null;
}
主页面结构分析
主页面实现分析
布局,最外层是相对布局:顶部是线性布局,里面两个 TextView;
中间是使用分类型的 RecyclerView
当滑动底部的时候显示跳转到顶部的按钮;
注意,实现该布局最好是相对布局和帧布局。
主页面布局实现 fragment_home.xml
首页布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".home.fragment.HomeFragment">
<include
android:id="@+id/titlebar"
layout="@layout/titlebar" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/titlebar" />
<ImageButton
android:id="@+id/ib_top"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/top_btn"
android:visibility="gone" />
</RelativeLayout>
标题栏
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ed3f3f"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_search_home"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:background="@drawable/search_home_shape"
android:drawableLeft="@drawable/home_search_icon"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:padding="5dp"
android:text="输入搜索信息"
android:textSize="13sp" />
<TextView
android:id="@+id/tv_message_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:drawableTop="@drawable/new_message_icon"
android:text="消息"
android:textColor="#fff" />
</LinearLayout>
RecyclerView 使用
//注意:版本号根据具体编译环境更改
compile 'com.android.support:recyclerview-v7:23.3.0'
初始化布局和设置监听
/**
* @author: Hashub
* @WeChat: NGSHMVP
* @Date: 2018/8/24 16:53
* @function:
*/
public class HomeFragment extends BaseFragment
{
private static final String TAG = HomeFragment.class.getSimpleName();
private RecyclerView rvHome;
private ImageView ib_top;
private TextView tv_search_home;
private TextView tv_message_home;
private HomeFragmentAdapter adapter;
private ResultBeanData.ResultBean resultBean;//返回的数据
@Override
public View initView()
{
Log.e(TAG, "主页的Fragment的UI被初始化了");
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;
}
@Override
public void initData()
{
super.initData();
Log.e(TAG, "主页的Fragment的数据被初始化了");
//联网请求主页的数据
getDataFromNet();
}
/**
* 联网请求主页的数据
*/
private void getDataFromNet()
{
String homeUrl = Constants.HOME_URL;
OkHttpUtils
.get()
.url(homeUrl)
.build()
.execute(new StringCallback()
{
/**
* 当请求失败的时候回调
* @param call
* @param e
* @param id
*/
@Override
public void onError(Call call, Exception e, int id)
{
Log.e(TAG,"首页请求失败=="+e.getMessage());
}
/**
* 当联网成功的时候回调
* @param response 请求成功的数据
* @param id
*/
@Override
public void onResponse(String response, int id)
{
Log.e(TAG,"首页请求成功=="+response);
//解析数据
processData(response);
}
});
}
/**
* 解析数据
* @param json
*/
private void processData(String json)
{
ResultBeanData resultBeanData = JSON.parseObject(json, ResultBeanData.class);
resultBean=resultBeanData.getResult();
if(resultBean!=null)
{
//有数据
//设置适配器
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);
}
else
{
//没有数据
}
Log.e(TAG,"解析成功=="+resultBean.getHot_info().get(0).getName());
}
/**
* 设置点击事件
*/
private void initListener()
{
//置顶的监听
ib_top.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//回到顶部
rvHome.scrollToPosition(0);
}
});
//搜素的监听
tv_search_home.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Toast.makeText(mContext, "搜索", Toast.LENGTH_SHORT).show();
}
});
//消息的监听
tv_message_home.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Toast.makeText(mContext, "进入消息中心", Toast.LENGTH_SHORT).show();
}
});
}
}
请求主页数据和解决数据
使用 OkHttpUtils 请求网络
下载地址:
https://github.com/hongyangAndroid/okhttputils
在 build.gradle(app) 配置如下:
compile 'com.zhy:okhttputils:2.6.2'
在 build.gradle(project)配置如下:
allprojects {
repositories {
jcenter()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
}
}
配置联网路径
/**
* @author: Hashub
* @WeChat: NGSHMVP
* @Date: 2018/8/26 9:10
* @function:配置各个页面联网地址
*/
public class Constants
{
// public static String BASE_URL = "http://192.168.51.104:8080/atguigu";
public static String BASE_URL = "http://192.168.1.102:80/atguigu";
/**
* 主页面的路径
*/
public static String HOME_URL = BASE_URL + "/json/HOME_URL.json";
/**
* 图片的基本路径
*/
public static String BASE_URL_IMAGE = BASE_URL + "/img";
}
使用 fastjson 解析数据
下载地址:
https://github.com/alibaba/fastjson
先添加 fastjson 的 jar 包,再配置本机ip及Tomcat服务器的端口号
//主页的路径
http://10.0.2.2:80/atguigu/json/HOME_URL.json
生成 JeanBean
使用 GsonFromat 生成 ResultBeanData 对象
主页面适配器
适配器 6 种类型
/**
* @author: Hashub
* @WeChat: NGSHMVP
* @Date: 2018/8/26 9:00
* @function:
*/
public class HomeFragmentAdapter extends RecyclerView.Adapter
{
/**
* 广告条幅类型
*/
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 static final String GOODS_BEAN = "goodsBean";
/**
* 用来初始化布局
*/
private LayoutInflater mLayoutInflater;
private Context mContext;
/**
* 数据
*/
private ResultBeanData.ResultBean resultBean;
/**
* 当前类型
*/
private int currentType = BANNER;
构造方法传入参数&getItemCount 和 getItemViewType
public HomeFragmentAdapter(Context mContext, ResultBeanData.ResultBean resultBean)
{
this.mContext = mContext;
this.resultBean = resultBean;
mLayoutInflater = LayoutInflater.from(mContext);
}
/**
* 得到类型
*
* @param position
* @return
*/
@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;
}
@Override
public int getItemCount()
{
//开发过程中从1-->6
return 6;
}
网友评论