激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - UGUI實現ScrollView無限滾動效果

UGUI實現ScrollView無限滾動效果

2022-03-11 13:09Tong1993222 C#

這篇文章主要為大家詳細介紹了UGUI實現ScrollView無限滾動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

抽空做了一個ugui的無限滾動的效果。只做了一半(向下無限滾動)。網上也看了很多教程,感覺還是按照自己的思路來寫可能比較好。搭建如下:

UGUI實現ScrollView無限滾動效果

content節點不添加任何組件。布局組件默認是會重新排版子節點的,所以如果子節點的位置變化,會重新排版,不能達到效果。size fitter組件也不加,自己寫代碼調整size大小(不調整大小,無法滑動)。

最主要的實現過程就是用queue來搬運cell。在向下滾動的過程中(鼠標上滑),頂部滑出view port的cell被搬運到底部續上。這點類似于queue的先見先出原則,再把dequeue出來的元素添加到末尾,就很類似于scrollview的無限滾動的原理了。在鼠標上滑的過程中,content的posy值是一直增加的,所以觸發滾動的條件就可以設定為位移之差大于cell的高度值即可。

 數據的刷新,數據到頭之后,不能再次進行滾動輪換了,這里用一組值來記錄初始化的一組cell顯示的是數據的哪一段。例如headnum和tainum。比如用20個cell顯示100條數據。初始化后,headnum就是0,tailnum就是19。上滑一行數據后,headnum=4,tailnum=23(這里假設是20個cell排成4列)。

下面是完整代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
public class uiscrollviewtest : monobehaviour {
 
  public recttransform content;
  public gameobject cell;
  // cell的初始化個數
  public int cellamount = 0;
  // 鼠標上滑時,存儲cell的queue。正序存儲
  public queue f_cellquee = new queue();
  // 鼠標下滑時,存儲cell的queue。到序存儲
  public queue b_cellquee = new queue();
  // cell的size
  public vector2 cellsize = new vector2(100,100);
  // cell的間隔
  public vector2 celloffset = new vector2(0,0);
  // 列數
  public int columncount = 0;
  private int rowcount;
  // 上一次content的位置
  public float lastpos;
  // 滾動的次數
  public int loopcount = 0;
  // cell顯示的數據段的開頭和結尾序號
  public int headnum = 0;
  public int tailnum;
 
  public sprite[] sp;
  public list<sprite> data;
 
 
  void start()
  {
    for (int i = 0; i < sp.length; i++)
    {
      data.add(sp[i]);
    }
 
    initialscrollview(data);
    tailnum = cellamount-1;
    lastpos = content.localposition.y;
    //debug.logerror("行數是:::" + rowcount);
 
    //debug.logerror("+++++++++++++++++  " + (5>>3));
  }
 
 
  void update()
  {
    // 觸發滾動。
    if (content.localposition.y - lastpos > cellsize.y && data.count - cellamount - loopcount*columncount >0)
    {
      //debug.logerror("11111111111  " + (data.count - cellamount - loopcount * columncount));
      loopscrolview(data);
      lastpos = content.localposition.y;
    }
  }
 
 
  
  
  // 初始化cell
  void initialscrollview(list<sprite> data)
  {
    for (int i = 0; i < cellamount; i++)
    {
      gameobject obj = instantiate(cell.gameobject);
      obj.transform.setparent(content);
      obj.name = "cell0" + i.tostring();
      obj.transform.getchild(0).getcomponent<text>().text = "cell0"+i.tostring();
      // 顯示默認的數據
      obj.getcomponent<image>().sprite = data[i];
    }
    // 初始化queue
    for (int i = content.childcount-1; i >= 0; i--)
    {
      b_cellquee.enqueue(content.getchild(i).gameobject);
    }
    for (int i = 0; i < content.childcount; i++)
    {
      f_cellquee.enqueue(content.getchild(i).gameobject);
    }
 
    // 計算行數
    if (cellamount % columncount >0)
    {
      rowcount = cellamount / columncount + 1;
    } else {
      rowcount = cellamount / columncount;
    }
 
    // 排列cell的位置
    int index = 0;
    for (int r = 1; r <= rowcount; r++)
    {
      for (int c = 1; c <= columncount; c++)
      {
        if (index < cellamount)
        {
          vector2 pos = new vector2(cellsize.x / 2 + (cellsize.x + celloffset.x) * (c-1), -cellsize.y / 2 - (celloffset.y + cellsize.y) * (r-1));
          content.getchild(index).getcomponent<recttransform>().setinsetandsizefromparentedge(recttransform.edge.top, 0, 100);
          content.getchild(index).getcomponent<recttransform>().setinsetandsizefromparentedge(recttransform.edge.left, 0, 100);
          content.getchild(index).getcomponent<recttransform>().anchoredposition = pos;
          index++;
        }
      }
    }
 
    vector2 v = content.sizedelta;
    // 初始化content的size
    content.sizedelta = new vector2(v.x, rowcount * cellsize.y + celloffset.y*(rowcount-1));
  }
 
 
  /// 保持content的大小,這里是保持大小為在cell的行數基礎上,向下多出bottomcount行的距離
  void setcontentsize(int uppercount, int bottomcount)
  {
    if (content.sizedelta != new vector2(content.sizedelta.x, content.sizedelta.y + bottomcount * (cellsize.y + celloffset.y)))
    {
      content.sizedelta = new vector2(content.sizedelta.x, content.sizedelta.y + bottomcount*(cellsize.y + celloffset.y));
    }
  }
 
  // 計算頂部的cell輪換到底部時的位置。以當前最后一行的最后一個cell的位置為基準計算。
  void setbottomcellposition(int index, recttransform rect, vector2 pos)
  {
    vector2 v = vector2.zero;
    if (cellamount % columncount == 0) // 整除。每一行都滿的情況。
    {
      float x = pos.x - cellsize.x * (columncount - index-1) - celloffset.x * (columncount-index-1);
      float y = pos.y - cellsize.y - celloffset.y;
      v = new vector2(x,y);
    }
    // 出現不滿行的情況。例如數據有103個,可以用23個cell來輪換。這樣就會出現不滿行的情況。
    // 這種情況下是頂部的一行cell順次接到底部不滿的行。例如23號cell后面接1號和2號cell,3號和4號cell填充到第“7”行
    else if (cellamount % columncount + index+1<=columncount)
    {
      float x = pos.x + cellsize.x * (index+1) + celloffset.x * (index+1);
      float y = pos.y;
      v = new vector2(x, y);
    }
    else
    {
      float x = pos.x - cellsize.x * (columncount - index-1) - celloffset.x * (columncount - index-1);
      float y = pos.y - cellsize.y - celloffset.y;
      v = new vector2(x, y);
    }
    //debug.logerror("++++++++++++++  " + pos+ "         "+ v);
    rect.anchoredposition = v;
    rect.setaslastsibling();
  }
 
  // 計算底部的cell輪換到頂部是的位置,基準位置是當前行的第一個cell。
  void setuppercellposition(int index, recttransform rect, vector2 pos)
  {
    vector2 v = vector2.zero;
    if (cellamount % columncount == 0) // 整除
    {
      float x = pos.x + cellsize.x * index + celloffset.x * index;
      float y = pos.y + cellsize.y + celloffset.y;
      v = new vector2(x, y);
    }
    //else if (cellamount % columncount + index + 1 <= columncount)
    //{
    //  float x = pos.x + cellsize.x * (index + 1) + celloffset.x * (index + 1);
    //  float y = pos.y;
    //  v = new vector2(x, y);
    //}
    //else
    //{
    //  float x = pos.x - cellsize.x * (columncount - index - 1) - celloffset.x * (columncount - index - 1);
    //  float y = pos.y - cellsize.y - celloffset.y;
    //  v = new vector2(x, y);
    //}
    //debug.logerror("++++++++++++++  " + pos+ "         "+ v);
    rect.anchoredposition = v;
    rect.setasfirstsibling();
  }
 
 
  // 鼠標上滑時,顯示當前cell的數據。同時記錄數據段的序號遞增。
  void showrestcelldata(image cell, int index)
  {
    if (tailnum< data.count-1)
    {
      debug.logerror("當前的序號是::::" + tailnum);
      tailnum++;
      headnum++;
      cell.sprite = data[tailnum];
    }
  }
 
  void showpreviouscelldata(image cell, int index)
  {
    if (headnum > 0)
    {
      debug.logerror("當前的序號是::::" + headnum);
      tailnum--;
      headnum--;
      cell.sprite = data[headnum];
    }
  }
 
 
  // 輪換的函數。每次亂換一行的cell。
  void loopscrolview(list<sprite> data)
  {
    setcontentsize(0, 1);
    loopcount++;
    recttransform rect2 = content.getchild(content.childcount - 1).getcomponent<recttransform>();
    for (int i = 0; i < columncount; i++)
    {
      gameobject obj = f_cellquee.dequeue() as gameobject;
      recttransform rect = obj.getcomponent<recttransform>();
      showrestcelldata(obj.getcomponent<image>(), i);
      setbottomcellposition(i, rect, rect2.anchoredposition);
      f_cellquee.enqueue(obj);
    }
  }
 
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/Tong1993222/article/details/80163764

延伸 · 閱讀

精彩推薦
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
主站蜘蛛池模板: 久久精品成人影院 | 羞羞的动漫在线观看 | 久久精品a一级国产免视看成人 | 国产精品午夜在线观看 | 欧美成人午夜一区二区三区 | 成人福利免费在线观看 | 97精品视频在线观看 | 毛片在线视频在线播放 | 日韩黄色免费观看 | 羞羞视频免费入口网站 | va视频| 九九精品在线观看视频 | 啪啪激情 | 成人免费自拍视频 | 91www成人久久 | 婷婷久久影院 | 免费观看又色又爽又黄的崩锅 | 久久久无码精品亚洲日韩按摩 | 在线免费小视频 | 一级做a爱片毛片免费 | 特级无码毛片免费视频尤物 | 91久久99热青草国产 | 在线成人免费网站 | 美女在线视频一区二区 | 精品二区在线观看 | 男男羞羞视频网站国产 | 欧美一区在线观看视频 | 国产乱淫av片免费网站 | 日韩毛片在线看 | 国产成人午夜精品 | 国内久久久久 | 国产精品午夜小视频观看 | 一级性色 | 福利在线国产 | 国产一区二区三区手机在线 | 亚洲午夜免费电影 | 黄色特级视频 | 最新日韩在线观看视频 | 毛片大全| 成人免费毛片在线观看 | 国产一区二区视频在线播放 |