android仿支付宝首页更多、应用编辑界面

版权声明: https://blog.csdn.net/xu_coding/article/details/80870334
[github地址](https://github.com/oldbirdy/recyclerdemo “github地址”) 项目越来越大,模块越来越多,首页上展示的东西又不能全部都展示出来,只能选择几个重要的模块展示出来。但是不同的用户关注的层面不一样,只好让用户自己去选择需要展示的应用。就像支付宝的应用编辑界面一样。
我的界面效果图 支付宝界面

整体介绍

总的来说实现了从json数据转化为当前界面,可以自由的编辑界面保存到本地。

主要界面布局 一个标题栏,下面是一个RecyclerView(主要是拖拽实现很方便)。中间放了一个水平的HorizontalScrollView。下面是一个存放所有列表的RecyclerView

<?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="match_parent"
    android:background="@drawable/bg_white"
    android:orientation="vertical">
    <RelativeLayout
        android:id="@+id/title"
        android:layout_width="fill_parent"
        android:layout_height="48dp"
        android:background="@drawable/bg_blue" >
       <TextView
            android:id="@+id/titletext"
            android:textSize="20sp"
            android:textColor="@color/white"
            android:layout_width="wrap_content"
            android:text="编辑我的应用"
            android:gravity="center_vertical"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />
        <TextView
            android:id="@+id/submit"
            android:textSize="20sp"
            android:textColor="@color/white"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerInParent="true"
            android:gravity="center_vertical"
            android:text="保存"/>
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:padding="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我的应用"
            android:textColor="#333333"
            android:textSize="16sp" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="(按住可拖动调整顺序)"
            android:textColor="#808080"
            android:textSize="13sp" />
    </LinearLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewExist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingRight="10dp" />
    <View
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:background="@color/line_color">
    </View>
    <HorizontalScrollView
        android:id="@+id/horizonLScrollView"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:scrollbarThumbHorizontal="@color/transparent"
        android:scrollbars="none">
        <RadioGroup
            android:id="@+id/rg_tab"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical"
            android:orientation="horizontal" />
    </HorizontalScrollView>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/line_color">
    </View>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewAll"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:paddingRight="10dp" />
</LinearLayout>

两个实体类 tabItem(记录每个tab项) 和FunctionItem(记录每个功能模块)

public class TabItem {
    private String tabName="";
    private ArrayList<FunctionItem> functionItems;
    }
public class FunctionItem {
    public String name;
    public boolean isSelect = false;
    public String imageUrl = "";
    public String background ="";
    }

为了方便,通过GSON实现了测试数据。在库文件中。可以去生成测试数据。写入到文件中。

  ArrayList<TabItem> tabItems = new ArrayList<>();
        ArrayList<FunctionItem> arrayList = new ArrayList<>();
        arrayList.add(new FunctionItem("充值中心",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("信用卡还款",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("生活缴费",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("城市服务",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("生活号",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("我的客服",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("我的快递",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("医疗健康",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("记账本",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("城市一卡通",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("发票管家",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("蚂蚁宝卡",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("车主服务",false,"icon_home_selected","#86c751"));
        arrayList.add(new FunctionItem("天天有料",false,"icon_home_selected","#86c751"));
        TabItem tabItem = new TabItem("便民生活",arrayList);
        tabItems.add(tabItem);

        ArrayList<FunctionItem> arrayList1 = new ArrayList<>();
        arrayList1.add(new FunctionItem("余额宝",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("花呗",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("芝麻信用",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("蚂蚁借呗",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("股票",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("保险服务",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("汇率换算",false,"icon_home_selected","#86c751"));
        arrayList1.add(new FunctionItem("理财小工具",false,"icon_home_selected","#86c751"));

        TabItem tabItem1 = new TabItem("财务管理",arrayList1);
        tabItems.add(tabItem1);

        ArrayList<FunctionItem> arrayList2 = new ArrayList<>();
        arrayList2.add(new FunctionItem("转账",false,"icon_home_selected","#86c751"));
        arrayList2.add(new FunctionItem("红包",false,"icon_home_selected","#86c751"));
        arrayList2.add(new FunctionItem("AA收款",false,"icon_home_selected","#86c751"));
        arrayList2.add(new FunctionItem("亲密付",false,"icon_home_selected","#86c751"));
        arrayList2.add(new FunctionItem("上银汇款",false,"icon_home_selected","#86c751"));
        arrayList2.add(new FunctionItem("话费卡转让",false,"icon_home_selected","#86c751"));
        TabItem tabItem2 = new TabItem("资金往来",arrayList2);
        tabItems.add(tabItem2);

        ArrayList<FunctionItem> arrayList3 = new ArrayList<>();
        arrayList3.add(new FunctionItem("游戏中心",false,"icon_home_selected","#86c751"));
        arrayList3.add(new FunctionItem("出境",false,"icon_home_selected","#86c751"));
        arrayList3.add(new FunctionItem("彩票",false,"icon_home_selected","#86c751"));
        arrayList3.add(new FunctionItem("人脸识别",false,"icon_home_selected","#86c751"));
        arrayList3.add(new FunctionItem("奖励金",false,"icon_home_selected","#86c751"));
        arrayList3.add(new FunctionItem("世界杯",false,"icon_home_selected","#86c751"));
        TabItem tabItem3 = new TabItem("购物娱乐",arrayList3);
        tabItems.add(tabItem3);

        ArrayList<FunctionItem> arrayList4 = new ArrayList<>();
        arrayList4.add(new FunctionItem("大学生活",false,"icon_home_selected","#86c751"));
        arrayList4.add(new FunctionItem("爱心捐赠",false,"icon_home_selected","#86c751"));
        arrayList4.add(new FunctionItem("蚂蚁森林",false,"icon_home_selected","#86c751"));
        arrayList4.add(new FunctionItem("蚂蚁庄园",false,"icon_home_selected","#86c751"));
        arrayList4.add(new FunctionItem("中小学",false,"icon_home_selected","#86c751"));
        arrayList4.add(new FunctionItem("运动",false,"icon_home_selected","#86c751"));
        TabItem tabItem4 = new TabItem("教育公益",arrayList4);
        tabItems.add(tabItem4);

        ArrayList<FunctionItem> arrayList5 = new ArrayList<>();
        arrayList5.add(new FunctionItem("淘票票",false,"icon_home_selected","#86c751"));
        arrayList5.add(new FunctionItem("滴滴出行",false,"icon_home_selected","#86c751"));
        arrayList5.add(new FunctionItem("饿了么外卖",false,"icon_home_selected","#86c751"));
        arrayList5.add(new FunctionItem("天猫",false,"icon_home_selected","#86c751"));
        arrayList5.add(new FunctionItem("淘宝",false,"icon_home_selected","#86c751"));
        arrayList5.add(new FunctionItem("火车票机票",false,"icon_home_selected","#86c751"));
        TabItem tabItem5 = new TabItem("第三方服务",arrayList5);
        tabItems.add(tabItem5);

        Gson gson = new Gson();
        String json = gson.toJson(tabItems);
        try {
            FileOutputStream fos = new FileOutputStream("ceshi.xml");
            fos.write(json.getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

有了测试数据之后,我将文件复制到了Assert目录下面。用来模拟数据请求。一般来说数据应该保存在服务器上。根据服务器上请求的数据。去生成页面。
第一个RecyclerView recyclerViewExist

 recyclerViewExist.setLayoutManager(new GridLayoutManager(this, 4));
        recyclerViewExist.setAdapter(blockAdapter);
        recyclerViewExist.addItemDecoration(new SpaceItemDecoration(4, dip2px(this, 10)));

        DefaultItemCallback callback = new DefaultItemCallback(blockAdapter);
        DefaultItemTouchHelper helper = new DefaultItemTouchHelper(callback);
        helper.attachToRecyclerView(recyclerViewExist);

blockAdapter主要是渲染一个item中图片和文字,绑定点击的时候事件

@Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(inflater.inflate(R.layout.layout_grid_item, parent, false));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final int index = position;
        FunctionItem fi = data.get(position);
        setImage(fi.imageUrl, holder.iv);
        holder.text.setText(fi.name);
        holder.btn.setImageResource(R.drawable.ic_block_delete);
        holder.btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FunctionItem fi = data.remove(index);
                if (listener != null) {
                    listener.remove(fi);
                }
                notifyDataSetChanged();
            }
        });
    }

通过DefaultItemCallback和DefaultItemTouchHelper实现了拖拽。核心代码

  public DefaultItemCallback(ItemTouchHelperAdapter touchHelperAdapter) {
        this.touchHelperAdapter = touchHelperAdapter;
    }
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许上下左右的拖动
        return makeMovementFlags(dragFlags, 0);
    }

recyclerViewAll下面的所有的内容。也只是提供了一个点击的回调和布局渲染。

 functionAdapter = new FunctionAdapter(this, allData);
        recyclerViewAll.setLayoutManager(gridManager);
        recyclerViewAll.setAdapter(functionAdapter);
        SpaceItemDecoration spaceDecoration = new SpaceItemDecoration(4, dip2px(this, 10));
        recyclerViewAll.addItemDecoration(spaceDecoration);

看一下中间horizonLScrollView 里面写了Radiogroup

向radiogoup添加radio.每次点击触发一下回调函数

 for (int i = 0; i < size; i++) {
                    FunctionItem item = tabs.get(i);
                    if(item.isTitle){
                        scrollTab.add(item.name);
                        RadioButton rb = new RadioButton(this);
                        rb.setPadding(padding, 0, padding, 0);
                        rb.setButtonDrawable(null);
                        rb.setGravity(Gravity.CENTER);
                        rb.setText(item.name);
                        rb.setTag(i);
                        rb.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                        try {
                            rb.setTextColor(getResources().getColorStateList(R.color.bg_block_text));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        rb.setCompoundDrawablesWithIntrinsicBounds(null, null, null, getResources().getDrawable(R.drawable.bg_block_tab));
                        rb.setOnCheckedChangeListener(onCheckedChangeListener);
                        rg_tab.addView(rb);
                    }
                }

当点击button的时候。根据上面rb.setTag(i)。这里的i。表示选中的元素是所有列表的第几个。每次点击的时候,调用下面的方法。移动到指定的位置

            private void moveToPosition(int position) {
        int first = gridManager.findFirstVisibleItemPosition();
        int end = gridManager.findLastVisibleItemPosition();
        if (first == -1 || end == -1)
            return;
        if (position <= first) {      //移动到前面
            gridManager.scrollToPosition(position);
        } else if (position >= end) {      //移动到后面
            isMove = true;
            scrollPosition = position;
            gridManager.smoothScrollToPosition(recyclerViewAll, null, position);
        } else {//中间部分
            int n = position - gridManager.findFirstVisibleItemPosition();
            if (n > 0 && n < allData.size()) {
                int top = gridManager.findViewByPosition(position).getTop();
                recyclerViewAll.scrollBy(0, top);
            }
        }
    }

当RecyclerView滑动的时候。更新一下HorizontalScrollView重的RadioGroup。

recyclerViewAll.addOnScrollListener(onScrollListener);  //添加一个滚动监听

 private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            try {
                if (isMove && newState == RecyclerView.SCROLL_STATE_IDLE) {
                    isMove = false;
                    View view = gridManager.findViewByPosition(scrollPosition);
                    if (view != null) {
                        int top = (int) view.getTop();
                        recyclerView.scrollBy(0, top);
                    }
                }
                if(newState==RecyclerView.SCROLL_STATE_DRAGGING){
                    isDrag = true;
                }else{
                    isDrag = false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if(isDrag){  //拖动过程中
                int position = gridManager.findFirstVisibleItemPosition();
                if(position>0){
                    for(int i=0;i<position+1;i++){
                        if(allData.get(i).isTitle){
                            currentTab = allData.get(i).name;
                        }
                    }
                    scrollTab(currentTab);
                }
            }
        }
    };



    private void scrollTab(String newTab) {
        try {
            int position = scrollTab.indexOf(currentTab);
            int targetPosition = scrollTab.indexOf(newTab);
            currentTab = newTab;
            if (targetPosition != -1) {
                int x = (targetPosition - position) * getTabWidth();
                RadioButton radioButton = ((RadioButton) rg_tab.getChildAt(targetPosition));
                radioButton.setOnCheckedChangeListener(null);
                radioButton.setChecked(true);
                radioButton.setOnCheckedChangeListener(onCheckedChangeListener);
                horizonLScrollView.scrollBy(x, 0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

至此所有的核心代码都在这里了。其中整个工程分为两个部分。一个app的activity的module。另一个是ceshi的lib。其中ceshi的lib只是用来生成对应的。

猜你喜欢

转载自blog.csdn.net/xu_coding/article/details/80870334