相关github源码链接:https://github.com/fuyinsheng/AA-.git
aa日常小助手是一个日常小工具软件 用于AA制分账中 1、采用一页式分账,简单明了 2、去除传统分账工具对人员的复杂操作,直接得出结果 3、本工具可用于旅行中的简单分账,只要输入总额并确认消费总人数,即可得出本次消费的平均分摊的账目,是旅途中的一款小工具
第一次提交 只是实现了简单的碎片和toptile布局
使用的是include 引用布局第二次提交 实现了底部的bar 使用include应用布局
中间的gird网格布局,这里使用了动态加载的方式
我使用的是用碎片的方式实现。
AppendMainBody(R.layout.main_body);
protected void AppendMainBody(int pResId)
{
LinearLayout _MainBody = (LinearLayout)v.findViewById(R.id.layMainBody);
View _View = LayoutInflater.from(getActivity()).inflate(pResId, null);
RelativeLayout.LayoutParams _LayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);
_MainBody.addView(_View,_LayoutParams);
}
首先通过v.findViewById找到在主碎片布局中的id为layMainBody的中间线性布局。
然后通过 LayoutInflater加载资源,并且返回一个View。
最后通过获取到的在主碎片中间的布局资源加载View
ActivityBase在基类中封装与业务无关的方法。简化代码编写过程。
例如:
protected void showMessage(Context context, String msg)
{
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
protected void startActivity(Class<?> pClass)
{
Intent _Intent = new Intent();
_Intent.setClass(this ,pClass);
startActivity(_Intent);
}
在ActivityFrame中把和业务相关的系统框架,界面初始化,设置等操作封装提取出来
例如:
AppendMainBody(R.layout.main_body);
protected void AppendMainBody(int pResId)
{
LinearLayout _MainBody = (LinearLayout)v.findViewById(R.id.layMainBody);
View _View = LayoutInflater.from(getActivity()).inflate(pResId, null);
RelativeLayout.LayoutParams _LayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);
_MainBody.addView(_View,_LayoutParams);
}
GirdView控件的使用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/gvAppGird"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:verticalSpacing="50dp" //设置网格的间隔距离
android:numColumns="3"> //设置每一行有几个
</GridView>
</RelativeLayout>
新建一个适配器类继承制Adaper,BaseAdaper是一个比较好用的适配器类
public class AdaperAppGrid extends BaseAdapter {
private class Holder //自己新建一个Holder类,来优化性能
{
ImageView ivIcon;
TextView tvName;
}
private Integer[] m_ImageInteger ={ //新建数组,存储图片的资源
R.mipmap.grid_payout,
R.mipmap.grid_bill,
R.mipmap.grid_report,
R.mipmap.grid_account_book,
R.mipmap.grid_category,
R.mipmap.grid_user,
};
private String[] mImagString = new String[6];
private Context mContext ;
public AdaperAppGrid(Context pContext) //适配器的构造函数,传入一个contxt上下文,然后通过context的getString()方法获取存储在String.xml中的字符串资源
{
mContext = pContext;
mImagString[0] = pContext.getString(R.string.appGridTextPayoutAdd);
mImagString[1] = pContext.getString(R.string.appGridTextPayoutManager);
mImagString[2] = pContext.getString(R.string.appGridTextStatisticsManager);
mImagString[3] = pContext.getString(R.string.appGridTextAccountBookManager);
mImagString[4] = pContext.getString(R.string.appGridTextCategoryManager);
mImagString[5] = pContext.getString(R.string.appGridTextUserManage);
}
@Override
public int getCount() { //获取要子项item的个数
return mImagString.length;
}
@Override
public long getItemId(int i) { //通过位置i,获取ItemId
return i;
}
@Override
public Object getItem(int i) { //通过位置获取所在位置的子项布局
return mImagString[i];
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) { //返回子项布局的View,通过
Holder _Holder;
if(view == null)
{
LayoutInflater _LayoutInflater = LayoutInflater.from(mContext);
view = _LayoutInflater.inflate(R.layout.main_body_item,null);
_Holder = new Holder();
_Holder.ivIcon = (ImageView)view.findViewById(R.id.ivIcon);
_Holder.tvName = (TextView)view.findViewById(R.id.tvName);
view.setTag(_Holder);
}
else
{
_Holder = (Holder)view.getTag();
}
_Holder.ivIcon.setImageResource(m_ImageInteger[i]);
LinearLayout.LayoutParams _layoutParams = new LinearLayout.LayoutParams(200,
200);
_Holder.ivIcon.setLayoutParams(_layoutParams);
_Holder.ivIcon.setScaleType(ImageView.ScaleType.FIT_XY);
_Holder.tvName.setText(mImagString[i]);
return view;
}
}
然后在代码中
private AdaperAppGrid mAdaperAppGrid;
mAdaperAppGrid = new AdaperAppGrid(getContext());
gvAppGrid.setAdapter(mAdaperAppGrid);
按钮点击时的背景颜色可以通过在drawable下新建xml文件,通过xml文件中的selector控制
android:state_selected 选中
android:state_focused 获得焦点
android:state_pressed点击
非触摸模式下获得焦点并单击时的背景图片
<item android:state_focused="true"
android:state_pressed="true" android:drawable="@drawable/pic2" />
触摸模式下 单击时的背景图片
<item android:state_focused="false"
android:state_pressed="true" android:drawable="drawable/pic3" />
<shape>
<gradient //颜色渐变
android:startColor="#ff8coo" //开始颜色
android:endColor = "#ffffff" //结束颜色
android:angle="270"/>渐变方向 必须是45的倍数
<stroke //按钮边缘
android:width=“2dp”//边缘宽
android:color="#dcdcdc" />边缘颜色
<corners //按钮四个圆角
android:radius="2dp" />半径
例如新建grid_selector.xml文件
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<corners android:radius="4dp" />
<gradient android:angle="270" android:endColor="#ff6f84aa" android:startColor="#ffabb8c9"></gradient>
</shape>
</item>
</selector>
然后在布局文件的相应控件通过android:listSelector指定相应的selector。
例如:
<GridView
android:id="@+id/gvAppGird"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:verticalSpacing="50dp"
android:listSelector="@drawable/grid_selector"
android:numColumns="3">
当某一个样式在很多地方都有使用,可以封装在values目录下的
style.xml中新建样式标签
例如
<style name="StyleListView">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:divider">@drawable/divider</item> //设置ListView控件的分隔资源
<item name="android:cacheColorHint">"@color/transparent</item>
</style>
然后在布局控件需要的地方引用
例如
<ListView android:id="+id/lvSlideList"
style="@style/StyleListView"
/>
封装自己的SlideMenu控件 SlideMenuView()
第三次提交,实现了点击底部状态栏,打开菜单列表,通过动态加载布局将底部bootmbar的位置移动到顶部状态栏的下面。
然后将Bootombar中的ListView展开。
1.在bottom_box.xml布局中定义一个ListView控件,位于线性布局中
<LinearLayout
android:id="@+id/layBottomListViewBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/layBottomBar">
<ListView
android:id="@+id/lvSlideList"
style="@style/StyleListView"></ListView>
</LinearLayout>
2.创建ListView的子项布局名为slidmenu_list_item.xml,子项布局中只有一个TextView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:padding="10dp"
android:background="@drawable/listview_selector">
<TextView
android:id="@+id/tvMenuName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="10dp"/>
</RelativeLayout>
3.封装一个子项布局的类名为SliderMenuItem。
public class SliderMenuItem {
private int mItemID;
private String mTitle;
public SliderMenuItem(int itemID, String title) {
mItemID = itemID;
mTitle = title;
}
public int getItemID() {
return mItemID;
}
public String getTitle() {
return mTitle;
}
public void setItemID(int itemID) {
mItemID = itemID;
}
public void setTitle(String title) {
mTitle = title;
}
}
4创建一个sliderMenuView,通过这个类来控制点击底部Bar,控制菜单项的打开和关闭,并且控制
ListView显示的菜单项内容。
public class SliderMenuView {
private Activity mActivity;
private List mMenuList;
private Boolean mIsClosed; //是否关闭
private RelativeLayout layBottomBox;
//动态加载,将Bootmbar的位置移动到Topbar下。
private void open()
{
RelativeLayout.LayoutParams _LayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
_LayoutParams.addRule(RelativeLayout.BELOW, R.id.IncludeTitle);
layBottomBox.setLayoutParams(_LayoutParams);
mIsClosed = false;
}
//动态加载,将Bootmbar的位置移动到父布局的底部。
private void close()
{
RelativeLayout.LayoutParams _LayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
200);
_LayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layBottomBox.setLayoutParams(_LayoutParams);
mIsClosed = true;
}
//开关函数,当菜单项关闭时执行打开操作,打开时执行关闭操作。
private void Toggle()
{
if(mIsClosed)
open();
else
close();
}
//添加SliderMenuItem,也就是ListView子布局显示的内容。
public void Add(SliderMenuItem pSliderMenuItem )
{
mMenuList.add(pSliderMenuItem );
}
//使将数据与ListView绑定,设置菜单子项的点击事件
public void BindList()
{
AdapterSlideMenu _AdapterSlideMenu = new AdapterSlideMenu(mActivity, mMenuList);
ListView _ListView =(ListView)mActivity.findViewById(R.id.lvSlideList);
_ListView.setAdapter(_AdapterSlideMenu);
_ListView.setOnItemClickListener(new onSlideMenuItemClickListener());
}
private void OnSlideMenuView()
{
}
//初始化数据
public void InitVarible()
{
mMenuList = new ArrayList();
mIsClosed = true;
}
public void InitView()
{
layBottomBox = (RelativeLayout)mActivity.findViewById(R.id.IncludeBottom);
}
//初始化Bootombar的监听器
public void InitListeners()
{
layBottomBox.setOnClickListener(new onSlideMenuClick());
}
//点击Bootombar就调用开关函数,展开或者关闭菜单项
private class onSlideMenuClick implements View.OnClickListener
{
@Override
public void onClick(View view) {
Toggle();}
}
private class onSlideMenuItemClickListener implements AdapterView.OnItemClickListener
{
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
}
}
//SilderMenuView的构造函数。进行一系列初始化控制逻辑
public SliderMenuView(Activity pActivity) {
mActivity = pActivity;
InitVarible();
InitView();
InitListeners();
}
}
3.ListView的适配器
3.1.因为适配器许多代码可以复用,构建了一个AdapterBase
public abstract class AdapterBase extends BaseAdapter {
private List mList;
private Context mContext;
private LayoutInflater mLayoutInflater;
public AdapterBase(Context pContext, List pList)
{
mContext = pContext;
mList = pList;
mLayoutInflater = LayoutInflater.from(mContext);
}
public List getList() {
return mList;
}
public LayoutInflater GetInflater()
{ return mLayoutInflater;
}
public Context GetContext()
{ return mContext;
}
public int getCount()
{
return mList.size();
}
public Object getItem(int pPosition)
{
return mList.get(pPosition);
}
public long getItemId(int pPosition)
{
return pPosition;
}
}
3.2.构建一个继承自AdapterBase的适配器
public class AdapterSlideMenu extends AdapterBase {
public AdapterSlideMenu(Context pContext, List pList) {
super(pContext, pList);
}
private class Holder
{
TextView tvMenuName;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
Holder _Holder;
if(view == null)
{
view = GetInflater().inflate(R.layout.slidemenu_list_item, null);
_Holder = new Holder();
_Holder.tvMenuName = (TextView)view.findViewById(R.id.tvMenuName);
view.setTag(_Holder);
}
else {
_Holder = (Holder)view.getTag();
}
SliderMenuItem _Item = (SliderMenuItem) getList().get(i);
_Holder.tvMenuName.setText(_Item.getTitle());
return view;
}
}
4在ActivityFrameBase中创建一个和用于创建SliderMenu的函数,子类可以
调用,负责SliderMenu的创建,其中传入的参数为pResId为ListView显示的内容
protected void CreateSlideMenu( int pResId)
{
mSliderMenuView = new SliderMenuView(getActivity());
String[] _MenuItenArray = getActivity().getResources().getStringArray(pResId);
for(int i = 0 ; i < _MenuItenArray.length;i++)
{
SliderMenuItem _SlideMenuItem = new SliderMenuItem(i, _MenuItenArray[i]);
mSliderMenuView.Add(_SlideMenuItem);
mSliderMenuView.BindList();
}
}
5.在values目录下创建arrays.xml文件,负责提供显示的bootombar中ListView要显示的资源数组。
<string-array name="SlideMenuActivityMain">
<item>软件帮助</item>
<item>关于软件</item>
<item>软件反馈</item>
<item>软件更新</item>
</string-array>
6.在MainActivity.java的onCreate中调用创建SliderMenu。
例如显示菜单项
CreateSlideMenu(R.array.SlideMenuActivityMain);
7.在SlideMenuView创建一个接口,然后让Activity实现这个接口。
实现在点击菜单项的时候,在点击事件里面回调Activity中实现的接口。
7.1.在SliderMenuView中创建一个接口,并定义一个变量。
private OnSlideMenuListenner mOnSlideMenuListenner;
public interface OnSlideMenuListenner
{
public abstract void onSlidMenuItemClick(View pView, SliderMenuItem pSlideMenuItemClick);
}
7.2.在MainAcitivity中实现这个接口,例如使用toast弹出点击的菜单项信息。
public class MainActivity extends ActivityFrame implements SliderMenuView.OnSlideMenuListenner {
.................
@Override
public void onSlidMenuItemClick(View pView, SliderMenuItem pSlideMenuItemClick) {
Toast.makeText(getActivity(), pSlideMenuItemClick.getTitle(),Toast.LENGTH_SHORT).show();
}
}
7.3.在SlideMenuView的构建函数中将实现了OnSlideMenuListenner接口的Activity传入,并转型为OnSlideMenuListenner。
这样就完整的实现了回调接口。
public SliderMenuView(Activity pActivity) {
mActivity = pActivity;
mOnSlideMenuListenner = (OnSlideMenuListenner)pActivity)
InitVarible();
InitView();
InitListeners();
}
7.4.在SlideMenuView的菜单子项的点击事件中回调Activity实现的回调接口。菜单子项的点击事件是在BindList函数中
注册的。通过适配器获取点击位置的Item。
private class onSlideMenuItemClickListener implements AdapterView.OnItemClickListener
{
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
SliderMenuItem _SliderMenuItem = (SliderMenuItem)adapterView.getItemAtPosition(position);
mOnSlideMenuListenner.onSlidMenuItemClick(view, _SliderMenuItem);
}
}
实现按菜单按钮可以打开或者关闭菜单项。
layBootomBox.setFocusableInTouchMode(true);//设置手机对焦
layBootomBox.setOnKeyListener(new OnKeyListener())
{
publick boolean onKey(View v, int keycode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_MENU &&
event.getAction()==KeyEvent.ACTION_UP)
{
Toggle();
}
return false;
}
}