《AA费用小助手》-笔记1

本文详细介绍了一款安卓应用的布局设计与菜单实现方法,包括使用include引用布局、动态加载布局、自定义适配器、按钮点击效果设置及菜单项展开与关闭的控制逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关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;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值