harmony下拉刷新,上啦加载更多组件

目录

一、设计思路

二、动手实现


一、设计思路

①、自定义一个组件,加载一个内含Head、ListContainer、Foot的布局文件。

②、监听此布局的触摸事件

③、监听ListContainer是否滑动到顶部或者底部。

④、根据②和③监听事件做相应的显示和隐藏(head、foot)布局即可。

二、动手实现

1、新建类RefreshListContainer继承ComponentContainer

2、新建包含Head、ListContainer、Foot布局文件,refresh_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:background_element="$color:dialog_btn_gray_color"
    ohos:orientation="vertical"
    >

    <DependentLayout
        ohos:id="$+id:head_layout"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:padding="10vp"
        >

        <Text
            ohos:id="$+id:head_text"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:center_in_parent="true"
            ohos:text="下拉刷新"
            ohos:text_size="17fp"
            />

        <Image
            ohos:id="$+id:head_image"
            ohos:height="40vp"
            ohos:width="40vp"
            ohos:image_src="$media:up_image"
            ohos:left_of="$+id:head_text"
            ohos:vertical_center="true"
            />
    </DependentLayout>

    <ListContainer
        ohos:id="$+id:list_container"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:background_element="white"
        ohos:below="$id:head_layout"
        />

    <DependentLayout
        ohos:id="$+id:foot_layout"
        ohos:height="70vp"
        ohos:width="match_parent"
        ohos:align_parent_bottom="true"
        ohos:padding="10vp"
        >

        <Text
            ohos:id="$+id:foot_text"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:center_in_parent="true"
            ohos:text="下拉刷新"
            ohos:text_size="17fp"
            />

        <Image
            ohos:id="$+id:foot_image"
            ohos:height="40vp"
            ohos:width="40vp"
            ohos:image_src="$media:up_image"
            ohos:left_of="$+id:foot_text"
            ohos:vertical_center="true"
            />
    </DependentLayout>
</DependentLayout>

3、在自定义的类中加载布局,初始化各个组件

private void init() {
    mRootLayout = (DependentLayout) LayoutScatter.getInstance(mContext)
            .parse(ResourceTable.Layout_refresh_layout, null, true);

    HiLog.error(LABEL, "init,rootLayout:%{public}s", mRootLayout);
    mHeadLayout = (DependentLayout) mRootLayout.findComponentById(ResourceTable.Id_head_layout);
    mFootLayout = (DependentLayout) mRootLayout.findComponentById(ResourceTable.Id_foot_layout);
    mListContainer = (ListContainer) mRootLayout.findComponentById(ResourceTable.Id_list_container);

    mHeadImage = (Image) mRootLayout.findComponentById(ResourceTable.Id_head_image);
    mHeadText = (Text) mRootLayout.findComponentById(ResourceTable.Id_head_text);
    mFootImage = (Image) mRootLayout.findComponentById(ResourceTable.Id_foot_image);
    mFootText = (Text) mRootLayout.findComponentById(ResourceTable.Id_foot_text);

    addComponent(mRootLayout);
}

4、设置监听事件

mRootLayout.setTouchEventListener(this::onTouchEvent);
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    int action = touchEvent.getAction();
    MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
    HiLog.error(LABEL, "action:%{public}s", action);
    switch (action) {
        case TouchEvent.PRIMARY_POINT_DOWN:
            HiLog.error(LABEL, "onTouchEvent:%{public}s", "PRIMARY_POINT_DOWN");

            mStartY = point.getY();
            break;
        case TouchEvent.PRIMARY_POINT_UP:
            HiLog.error(LABEL, "onTouchEvent:%{public}s", "PRIMARY_POINT_UP");
            HiLog.error(LABEL, "isPull:%{public}s", isPull);
            if (isPull) {
                int dis = (int) (mEndY - mStartY);
                HiLog.error(LABEL, "dis:%{public}s", dis);
                mHeadLayout.setMarginTop(0);
                pullLoadingStatus();
                isPull = false;
                if (this.mRefreshListener != null) {
                    this.mRefreshListener.pullRefresh();
                }
                mListContainer.setEnabled(true);
                // isLoading = true;
            }

            if (isUp) {
                int dis = (int) (mStartY - mEndY);
                HiLog.error(LABEL, "dis:%{public}s", dis);
                mFootLayout.setMarginBottom(0);
                HiLog.error(LABEL, "mFootLayoutHeight:%{public}s", mFootLayoutHeight);
                mListContainer.setMarginBottom(mFootLayoutHeight);
                this.mBaseItemProvider.notifyDataSetItemInserted(mBaseItemProvider.getCount()-1);
                upLoadingStatus();
                isUp = false;
                if (this.mRefreshListener != null) {
                    this.mRefreshListener.upLoadingMore();
                }
                mListContainer.setEnabled(true);
            }
            break;
        case TouchEvent.POINT_MOVE:
            HiLog.error(LABEL, "onTouchEvent:%{public}s", "HOVER_POINTER_MOVE");
            mEndY = point.getY();
            HiLog.error(LABEL, "onTouchEvent,mEndY:%{public}s,mStartY:%{public}s", mEndY, mStartY);
            HiLog.error(LABEL, "mListContainer.canScroll(DRAG_UP):%{public}s", mListContainer.canScroll(DRAG_UP));

            HiLog.error(LABEL, "isSocllTop:%{public}s", isSocllTop);
            if (!isLoading) {
                if (isSocllTop && !isUp) {
                    if (mEndY - mStartY > 50) {
                        isPull = true;
                        if (pullAnimator != null) {
                            pullAnimator.stop();
                            mHeadImage.setRotation(0);
                        }
                        mHeadLayout.setVisibility(VISIBLE);
                        mHeadLayout.setMarginTop((int) (mEndY - mStartY) - 50);
                        if (mEndY - mStartY > 50 && mEndY - mStartY < 150) {
                            pullDefault();
                        } else {
                            pullStatus();
                        }
                        mListContainer.setEnabled(false);
                    }
                }
                if (!mListContainer.canScroll(DRAG_UP) && !isPull) {
                    if (mStartY - mEndY > 50) {
                        isUp = true;
                        if (upAnimator != null) {
                            upAnimator.stop();
                            mFootImage.setRotation(0);
                        }

                        HiLog.error(LABEL, "mStartY - mEndY:%{public}s", mStartY - mEndY);
                        mFootLayout.setVisibility(VISIBLE);
                        int des = (int) (mStartY - mEndY) - 50;
                        mListContainer.setMarginBottom(mFootLayoutHeight + des);
                        mFootLayout.setMarginBottom(des);
                        HiLog.error(LABEL, "mFootLayoutHeight:%{public}s", mFootLayoutHeight);
                        this.mBaseItemProvider.notifyDataSetItemInserted(mBaseItemProvider.getCount()-1);
                        if (mStartY - mEndY > 50 && mStartY - mEndY < 150) {
                            upDefault();
                        } else {
                            upStatus();
                        }
                      //  mListContainer.setEnabled(true);
                    }
                }
            }

            break;
        default:
    }
    return true;
}

5、新建回调事件

package com.yan.refreshlistcontainer.listener;

public interface RefreshListener {

    public void pullRefresh();

    public void upLoadingMore();
}

6.提供方法供外部调用

//下拉刷新和上啦加载更多完成时调用
public void completeLoading() {
    if (pullAnimator != null) {
        pullAnimator.stop();

    }
    mHeadLayout.setVisibility(HIDE);
    pullDefault();

    if (upAnimator != null) {
        upAnimator.stop();
    }
    mFootLayout.setVisibility(HIDE);
    mListContainer.setMarginBottom(0);
    upDefault();
}

//给ListContainer设置适配器
public void setItemProvider(BaseItemProvider baseItemProvider) {
    this.mBaseItemProvider = baseItemProvider;
    mListContainer.setItemProvider(this.mBaseItemProvider);

}
//设置上啦和下拉的监听事件
public void setRefreshListener(RefreshListener refreshListener) {
    this.mRefreshListener = refreshListener;
}

7、ability使用

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">

   <com.yan.refreshlistcontainer.component.RefreshListContainer
       ohos:id="$+id:refresh_list"
       ohos:height="match_parent"
       ohos:width="match_parent"/>

</DirectionalLayout>
package com.yan.refreshlistcontainer.slice;

import com.yan.refreshlistcontainer.ResourceTable;
import com.yan.refreshlistcontainer.bean.ListBean;
import com.yan.refreshlistcontainer.component.RefreshListContainer;
import com.yan.refreshlistcontainer.listener.RefreshListener;
import com.yan.refreshlistcontainer.provider.RefreshListProvider;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import java.util.ArrayList;
import java.util.List;

public class MainAbilitySlice extends AbilitySlice {
    private RefreshListContainer mRefreshList;
    private List<ListBean> mData = new ArrayList<>();
    private MyEventHandler myHandler;
    private RefreshListProvider refreshListProvider;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        mRefreshList = (RefreshListContainer) findComponentById(ResourceTable.Id_refresh_list);

        initList();
        EventRunner runner = EventRunner.create(true);
        myHandler = new MyEventHandler(runner);

        refreshListProvider = new RefreshListProvider(MainAbilitySlice.this, mData);
        mRefreshList.setItemProvider(refreshListProvider);
        mRefreshList.setRefreshListener(new RefreshListener() {
            @Override
            public void pullRefresh() {
                ListBean mListBean = new ListBean();
                mListBean.setAge(999);
                mListBean.setName("刷新新增Item");
                mData.add(0, mListBean);
                myHandler.sendEvent(1000, 3000);
            }

            @Override
            public void upLoadingMore() {
                ListBean mListBean = new ListBean();
                mListBean.setAge(999);
                mListBean.setName("加载更多新增Item");
                mData.add(mListBean);
                myHandler.sendEvent(1000, 3000);
            }
        });
    }

    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;

            switch (eventId) {
                case 1000:
                    getUITaskDispatcher().syncDispatch(new Runnable() {
                        @Override
                        public void run() {
                            refreshListProvider.notifyDataChanged();
                            mRefreshList.completeLoading();
                        }
                    });

                    break;

                default:
                    break;
            }
        }
    }

    private void initList() {
        for (int i = 0; i < 100; i++) {
            ListBean mListBean = new ListBean();
            mListBean.setAge(i);
            mListBean.setName("测试" + i);
            mData.add(mListBean);
        }
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

至此大概的流程已经完成。

Screenshot_20210707_162751_com.yan.demo.jpg

Screenshot_20210707_162759_com.yan.demo.jpg

Screenshot_20210707_162803_com.yan.demo.jpg

Screenshot_20210707_162821_com.yan.demo.jpg

项目地址:https://gitee.com/WangYan2017/refresh-list-container

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值