一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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
主站蜘蛛池模板: 天天干天天操天天爽 | 强制高h | 纲手被强喷水羞羞漫画 | 亚洲一级视频在线观看 | 我的妹妹最近有点怪免费播放 | 国产精品九九久久一区hh | 欧美国产日韩综合 | 国产精品视频二区不卡 | 国产精品青青青高清在线 | ak福利影院 | 国产精品中文字幕 | 色悠久久久久综合网小说 | 舔穴吸奶| 亚洲国产精品ⅴa在线观看 亚洲国产高清一区二区三区 | 范冰冰特黄xx大片 | 欧美性色黄大片四虎影视 | 我的年轻漂亮继坶三级 | 国产欧美日韩视频在线观看一区二区 | 欧美日韩国产一区二区三区在线观看 | 摸逼小说| 四虎在线最新永久免费 | 91九色麻豆 | www.羞羞视频 | 国模人体aⅴ | 亚洲久草在线 | 男女交性特一级 | 精品国产福利一区二区在线 | h视频免费高清在线观看 | 欧美久久影院 | 美女扒开奶罩让男人吃奶 | 亚洲国产在线综合018 | 无人视频在线观看完整版高清 | 911爱豆传媒国产 | 96av视频在线观看 | 99精品久久久久久 | 成人精品福利 | 1024国产精品视频观看 | 精品国产线拍大陆久久尤物 | 国产乱妇无码大片在线观看 | 日本国产一区二区三区 | 亚洲精品无码不卡在线观看 |