简介

  鸿蒙OS 开发SDK中关于长列表的完毕ListContainer的完毕较为简略,无法想RecyclerView相同经过运用不同的Layoflutter是什么意思utManager来完毕杂乱布局因而无法快速完毕瀑布流效果。
但鸿蒙OS也都支撑控件的Measure(onEstimateSFlutterize),layout(onArrange) 和数组去重工作的处理。完全能够在鸿蒙OS中自界flutter菜鸟教程说一个布局来完毕RecyclerVigit教程ew+Laygiti轮胎outManager的效Flutter果,以此来完毕瀑布流等杂乱效果。

自界说布局

  关于鸿蒙OS自界说布局在官网上有介绍,首要完毕onEstimateSize来测量控件巨细和onArrange完毕布局,这儿咱们将子控件的招认和测量摆放完全交LayoutManager来完毕。一起咱们要支撑滑动,git指令这儿用Component.DraggedListener完毕。因而咱们的布局容器十分简略,调用LayoutManagGiter进行测量布局,一起关于滑动工作,招认滑动后的视窗,调用LayoutManager的fill函数招认填满视窗的子容器集结,然后触发从头制作。中心代码如下

public class SpanLayout extends ComponentContainer implementflutter结构优缺点s ComponentContainer.EgithubstimateSizeListeneflutter中文官网r,
ComponentContainer.ArrangeListener, Component.CanAcceflutter开发ptScrollListener, Component.ScrolledListener, Component.TouchEventListener, Component.DraggedListener {
private BaseItemProvidfluttershyerflutter是什么意思 mProvider;
public SpanLayout(Context contexgiti轮胎t) {
super(cflutter结构优缺点ontext);
setEstimateflutter是什么意思SizeListener(this);
setArrangeListener(this);
setDraggedListener(D数组的界说RAG_VERTICAL,tflutter菜鸟教程his);
}
@Override
public boolean onEstimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {
int width = Component.Estimflutter中文官网ateSpec.getSize(wid数组thEstimatedConfig);
int heighflutter菜鸟教程t = Component.EstimateSpec.getSize(heightEflutter中文官网stimatedConfig);
setEstimatedSizflutter开发e(
Component.EstimateSpec.getChildSizegit教程WithMode(width, widthEstimatedConfig, EstimateSpec.UNCONSTRAINT),
Component.EstimateSpec.getChildSizeWithMode(gitlabheight, heightEstimatedConfig, EstimateSpec.UNCONSTRAINT));
mLayoutManager.setEstimateSize数组(widthEstimatedConfig,heflutter结构ightgitiEstimatedConfig);
//        measuflutteredreChild(widthEstimatedConfig,heightEstimatedCongiteefig);
return true;
}
@Override
pubgiteelic boolea数组和链表的差异n onArrange(int left, int top, int width, int height) {
//榜首次fill,从igititem0初步一贯到leftH数组排序eight和rightHeight都大于height中止。
if(mRecycler.getAttachedScrap().igithub永久回家地址sEflutter怎样读音发音mpty())数组的界说{
mLayoutManag数组去重er.fill(left,top,left+width,top+height,DIRECTION_UP);
}
//        removeAllComponents(); //调用removeAllComponents的话会一贯启航从头制作。
for(RecyclerItem item:mRecycler.getAttach数组排序edScrap()){
item.chgiti轮胎ild.arrange(item.positionX+item.marginLeft,scrollY+item.positionY+item.margingit指令Top,item.width,item.height);
}
return true;
}
@Oflutter中文官网verride
public void onDragStart(Component component数组去重, D数组排序ragInfo dragInfo) {
startY数组 = dragInfo.startPoint.getPointYToInt();
}
@Override
public void onDragUpdate(Coflutter结构优缺点mponent component, D数组排序ragInfo dragflutter开发Info) {
int dt = dragInfo.updatePoint.ge数组去重办法tPoinflutter怎样读音发音tYToInt() - startY;
int tryScrollY = dt + scrollY;
startY = dragInfo.updatePoint.getPointYToInt();
mDirection = dtfluttershy<0?DIRflutter结构ECTION_UP:DIRECTION_DOWN;
mChange = mLayoutManager.fill(0, -tryScrollY,getEstflutter怎样读音发音imatedW数组去重idth(),-tryScrollY+getEstimatedHeigflutter怎样读音发音ht(),mDirection);
if(mChange){
scrollY = tryScrollY;
postLayo数组词ut();
}
}
}

瀑布流LayoutManage数组去重r

LayoutManager首要是用来招认子控件的布局,重点是要完毕fill函数Git,用于招认关于一个视窗内的子控件。

咱们界说一个Span类,来记载某一列瀑布当时startLine和endLine情况数组c言语,关于spanNum列的瀑布流,咱们创立Span数组来记载数组去重情况。

例如向上翻滚,当一个子控件满意bottom小于视窗top时需求收回,当一个子控件的bottom小于视窗的bottom是数组去重办法阐明其下方需有子控件填充。由于瀑布流是多列的且每个子控件高度不同,因而咱们不能简略的判别当时闪现的榜首个子控件是否要收回,最终一个子控件下方是否需求填充来完毕布满视窗的作业。咱们用while循环+双端行列,经过确保一切的Span其startLine都数组和链表的差异小于视窗top数组c言语,endLine都大于视窗bottom来完毕布满视窗的作业。中心fill函数完毕如下:

public synchronized boolean fill(float left,float top,float rigithub永久回家地址ght,float bottom,int directiflutteringon数组排序){
int spanWidth = mWidthSize/mSpanNum;
if(数组去重办法mSpans == null){
mSpans = new Span[mSpanNum];
for(int i=0;i<mSpanNum;i++){fluttered
Span span = new Span();
span.index = i;
mSpans[i] = span;
span.left = (int) (left + i*spanWidth);
}
}
LinkedList<RecyclerItem> attached = mRecycler.getAt数组去重tachedSc数组rap();
ifgithub永久回家地址(attached.isEmpty()){
mRecycler.getAllScrap().clear();
int count = mProvider.getCount()fluttershy;
int okSpan = 0;
for (int i=0;i<count;i++){
Span span = getMinSpanWithEndLine();
RecyclerIte数组指针m item = fillChild(span.left,span.endLine,i);
item.span = span;
if(item.positiongithub中文官网网页Y>=top && item.positionY<=bottom+item.height){//在闪现区域
mRecycler.addItem(i,item);
mRecycler.attachItemToEnd(item);
}else{
mRecycler.recycle(item);
}
span.endLine += item.height+item.m数组公式arginTop+item.marginBottom;
if(span.endLine>bottom)giti轮胎{
okSpan++;
}
if(okSpan>=mSgiti轮胎panNum){
breflutteringak;
}
}
return true;
}else{
if(direction == DIRECTION_UPflutter中文官网){
RecyclerItem last = attached.peekLast();
int count = mProvideGitr.getCount();
if(last.index == count-1 &amFlutterp;& last.getBottom()<=bottom){//现已究竟
return false;
}else{
//先收回
RecyclerItem first = attached.peekFir数组排序st();
while(first != null && first.getBottom()<top){
mRecycler.recycle(first);//recgitlabycle本身会removFluttere
first.span.gitistartLine += first.getVSpace();
first =github永久回家地址 attached.peekFirst()数组去重办法;
}
Span minEndLineSpan = getMinSpanWithEndLine()gitee;
int index = last.index+1;
whFlutterile(index<count &数组初始化amp;& minEndLineSpan.endLine<=bottom){//需求填充
RecyclerItem item;
if(mRecycler.getAllScrap().size()>index){gitee
item = mRecycler.getAllScrap().get(index);
mRecyclergiti轮胎.recoverToEnd(item);
}else{
item = fillChild(minEndLineSpan.left,minEndLineSpan.endLine,index);
item.span = minEgitlabndLineSpan;
mRecycler.atta数组的界说chItemToEnd(item);
mRecycler.addItem(index,item);
}
item.sFlutterpan.endLine += item.getVSpace();
minEndLineSpan = getMinSpangithubWithEndLine();
index++;
}
return true;
}
}giteeelse if(direction == DIRECTION_DOWN){
RecyclerItem firflutter结构st = attached.peekFirst();
int count = mProvider.ggiteeetCount();
if(first.index ==数组 0 && first.getT数组去重op()>=top){//现已到顶
return false;
}else{
//先收回
RecyclerItflutter是什么意思em last = atgitlabtached.peekLast();
while(lflutter结构ast != null && last.getTop()>bottom){
mRecycler.recycle(last);//recycle本身会remove
last.span.endLine -= last.getVSpace();
last = attached.peekFirst();
}
Span maxStartLineSpan = getMaxSpanWithStartLine();
int index = first.index-1;
while(index>=0 && maxStartLiflutter中文官网neSpan.startLine>=top){//需求填充
RecyclerItem item = mRecycler.getAllScrap().get(index);
ifflutter结构优缺点(item != null){
mRecycler.recove数组c言语rToStart(item);
item.span.startLine -= item.getVSpace();
}else{
//理论上不存在
}
maxS数组词tartLineSpan = getMaxSpanWithStartLine();
index--;
}
return true;
}
}
}
return true;
}

Item收回

关于长列表,必定要有类似于RecyclerView的收回机制。item的收回和github永久回家地址复原在LayoutManager的fill函数中触发,经过Reycler完毕。

简略的运用了mAttacthedScrgit教程ap来保存当时视窗上闪现的Item和mCacheScrap来保存被收回的控件。这儿的规划就是对RecyclerView的收回机制的简化。

不同的是参阅Flutter中三棵树的概念,界说了Rgithub是干什么的ecycleIte数组排序m类,用来记github永久回家地址载每个Item的左上角坐标和宽高值,只要在视窗上闪现的Item会绑定组件。由于未绑定组件时的RecycleItem是十分轻量级的,因而内存的损耗根本能够疏忽fluttered。咱们用mAllScr数组c言语ap来按次序保存一切的RecycleItem方针,用来复用。当康复一个mAllScrap中存在的Item时,其坐标和宽高都现已招认。

Recycleflutter开发r的完毕中心代码如下:

public class Recycler {
publi数组c static final int DIRECTION_UPgithub = 0;github是干什么的
public static final int DIRECTION_DOWN = 2;
private ArrayList<RecyclerItem> mAllScrap = new ArrayList<>();
private LinkedLflutter怎样读音发音ist<RecyclerItem> mAttacFlutterhedScrap = ngit指令ew LinkedList<>();
private LinkedList<Component> mCacheScrap = new LinkedList<Component>();
private BaseItemProvider mProvider;
priv数组去重ate SpanLayout mSpanLayout;
private int direction = 0;
publi数组的界说c Recycler(SpanLayout layout, BaseItemProvid数组指针er provider) {
this.mSpanLayout = layout;
this.mProvider = provider;Git
}
public Arra数组排序yList<RecyclerItem> getAllScrap() {
return mAllScrap;
}
public LinkedList<RecyclerItem> getAttachedScr数组排序ap() {
return mAttachedScrap;
}
public void cacheItem(数组和链表的差异int index, Recyc数组排序lerItem item) {
mAllScrap.add(index, item);
}
public void attachComponent(RecyclerItem item) {
mAttachedScrap.add(item);
}
public Component getView(int index, ComponentContainer container) {
Component cache = mCacheScrap.poll();
return mProvider.getComponent(index, cache, container);
}
public void addItem(int indgit指令ex,RecyclerItem item) {
mAllScrap.add(index,item);
}
public void attachItemToEnd(RecyclerItem item) {
mAttachedScrap.add(igititem);
}
public void attachItemToStart(RecyclerItem igithub中文官网网页tem) {
mAttaflutter开发chedScrap.add(0,item);
}
public void recycle(RecyclerItem item) {
mSpanLayout.remove数组排序Component(item.child);
mAttachedScrap.remove(item);
mCacheScrap.push(item.child)fluttershy;
item.child = null;
}
pub数组排序lic void recoverToEnd(RecyclerItem item) {
Component child = mPr数组去重办法ovider.getComponent(item.index,flutter是什么意思 mCacheScfluttershyrap.poll(), mSpanLayout);
child.estimateSize(
Component.EstimateSpec.getSizeWithMode(item.width, Component.EstimateSpec.PRECISE),
Component.EstimateSpec.getSizeWitgithub中文官网网页hMode(item.height, Component.EstimateSpec.PRECISE)
);
it数组排序em.child = child;
mAttachedScrap.add(item);
mSpaflutter中文官网nLayout.addComponent(child);
}
public void recoverToStart数组c言语(RecyclerItem it数组去重em) {
Component child = mP数组c言语rovider.getCom数组指针ponent(item.inde数组指针x, mCacheScrflutteringap.poll(), mSpanLayout);
child.estimateSize(
Component.EstimateSpec.getSiz数组eWithMode(item.width, Component.EstimateSpec.PRECISE),
Component.EstimateSpec.getSizeWithMode(item.height, Component.EstimateSpec.githubPRECISE)
);
item.c数组词hild = child;
mAttachedScrap.agit指令dd(0,item);
mSpanLayout.flutter结构优缺点addComponent(child);
}
}

总结

鸿蒙OS的开发SDK中基础才华都现已提供全面了,完全能够用来完毕一些杂乱效果。flutter中文官网这儿完毕的SpanLayout+LayoutManager+Recycler的根本是一个无缺的杂乱列表完毕,其他布局效果也能够经过完毕不同的LayoutManager来完毕。

无缺代码在自己的码云项目上 ,在com.profougit指令nd数组排序.notes.component包下,路过的请帮助点个star。gitee.com/profound-la…

原文链接:devflutter结构eloper.huawei.com/consumer/git指令cn…

原作者:zjwujlei