浏览代码

Add infinite scroll chat list.

/DatePickerDemo
shiyun wen 3 年前
当前提交
4039578e
共有 4 个文件被更改,包括 135 次插入133 次删除
  1. 10
      AwesomeUIWidgets/Assets/Scenes/ChatRoomScene.unity
  2. 100
      AwesomeUIWidgets/Assets/Scenes/SimpleWorldSpaceUI.unity
  3. 32
      AwesomeUIWidgets/Assets/Scripts/ChatPage.cs
  4. 126
      AwesomeUIWidgets/Assets/Scripts/Widgets/chat_list.cs

10
AwesomeUIWidgets/Assets/Scenes/ChatRoomScene.unity


m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1315574208}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 113}
m_LocalPosition: {x: 0, y: 0, z: 232}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1558042840}

m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 277.64478, y: 152}
m_AnchoredPosition: {x: -46, y: 152}
m_SizeDelta: {x: 398, y: 784}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1315574210

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1558042839}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalPosition: {x: 0, y: 0, z: -125}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1315574209}

m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 1928952342}
m_Texture: {fileID: 1916630145}
m_UVRect:
serializedVersion: 2
x: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1558042839}
m_CullTransparentMesh: 0
--- !u!28 &1928952342
--- !u!28 &1916630145
Texture2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}

100
AwesomeUIWidgets/Assets/Scenes/SimpleWorldSpaceUI.unity


m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 169, y: -153}
m_AnchoredPosition: {x: 94, y: -153}
m_SizeDelta: {x: 300, y: 400}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &373829884

m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 1431343988}
m_Texture: {fileID: 492280231}
m_UVRect:
serializedVersion: 2
x: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 373829882}
m_CullTransparentMesh: 0
--- !u!28 &492280231
Texture2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_ImageContentsHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0
serializedVersion: 3
m_Width: 0
m_Height: 0
m_CompleteImageSize: 0
m_TextureFormat: 0
m_MipCount: 1
m_IsReadable: 1
m_IgnoreMasterTextureLimit: 0
m_IsPreProcessed: 0
m_StreamingMipmaps: 0
m_StreamingMipmapsPriority: 0
m_AlphaIsTransparency: 0
m_ImageCount: 0
m_TextureDimension: 2
m_TextureSettings:
serializedVersion: 2
m_FilterMode: 1
m_Aniso: 1
m_MipBias: 0
m_WrapU: 0
m_WrapV: 0
m_WrapW: 0
m_LightmapFormat: 0
m_ColorSpace: 0
image data: 0
_typelessdata:
m_StreamData:
offset: 0
size: 0
path:
m_OriginalWidth: 0
m_OriginalHeight: 0
m_OriginalAssetGuid: 00000000000000000000000000000000
--- !u!1 &705507993
GameObject:
m_ObjectHideFlags: 0

m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!28 &1431343988
Texture2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_ImageContentsHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0
serializedVersion: 3
m_Width: 0
m_Height: 0
m_CompleteImageSize: 0
m_TextureFormat: 0
m_MipCount: 1
m_IsReadable: 1
m_IgnoreMasterTextureLimit: 0
m_IsPreProcessed: 0
m_StreamingMipmaps: 0
m_StreamingMipmapsPriority: 0
m_AlphaIsTransparency: 0
m_ImageCount: 0
m_TextureDimension: 2
m_TextureSettings:
serializedVersion: 2
m_FilterMode: 1
m_Aniso: 1
m_MipBias: 0
m_WrapU: 0
m_WrapV: 0
m_WrapW: 0
m_LightmapFormat: 0
m_ColorSpace: 0
image data: 0
_typelessdata:
m_StreamData:
offset: 0
size: 0
path:
m_OriginalWidth: 0
m_OriginalHeight: 0
m_OriginalAssetGuid: 00000000000000000000000000000000
--- !u!1 &1882612338
GameObject:
m_ObjectHideFlags: 0

m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2074331820}
m_LocalRotation: {x: 0, y: -0.078459024, z: 0, w: 0.99691737}
m_LocalPosition: {x: 200, y: 187, z: 780}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -80, y: -1, z: 229}
m_LocalEulerAnglesHint: {x: 0, y: -9, z: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

32
AwesomeUIWidgets/Assets/Scripts/ChatPage.cs


using System.Linq;
using ChatComponents;
using uiwidgets;
using Unity.UIWidgets.async;
using Unity.UIWidgets.cupertino;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;

{
public readonly ChatComponents.User _user = new ChatComponents.User("06c33e8b-e835-4736-80f4-63f44b66666c");
private List<ChatComponents.Message> _messages = new List<ChatComponents.Message>();
public int _page = 0;
public override void initState()
{

var textMessage = new ChatComponents.TextMessage(
_user,
createdAt: DateTime.Now.Millisecond,
id: "b4878b96-efbc-479a-8291-474ef323aaaa",
id: "b4878b96-efbc-479a-8291-474ef323aa" + _messages.Count.ToString(),
private Future _handleEndReached()
{
List<ChatComponents.TextMessage> messages = new List<ChatComponents.TextMessage>();
List<string> ids = new List<string>() { };
for (int i = 1; i < 10; i++)
{
ids.Add(i.ToString());
}
foreach (var id in ids)
{
messages.Add(new ChatComponents.TextMessage(
_user,
id: "b4878b96-efbc-479a-8291-474ef323aa" + id,
text: id + "......"
) );
}
setState(()=> {
{
_messages.AddRange(messages);
_page = _page + 1;
}
});
return Future.value();
}
private void _loadMessages()
{
List<ChatComponents.Message> results = new List<ChatComponents.Message>();

},
onTextChanged : (_str) => { },
onSendPressed: _handleSendPressed,
onEndReached: _handleEndReached,
//onEndReachedThreshold: 0.65f,
user: _user
)

126
AwesomeUIWidgets/Assets/Scripts/Widgets/chat_list.cs


using System;
using System.Collections.Generic;
using System.Linq;
using uiwidgets;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.async;

using Unity.UIWidgets.ui;
using Unity.UIWidgets.scheduler;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
namespace UIWidgetsSample
{

{
/// Used for pagination (infinite scroll) together with [onEndReached].
/// When true, indicates that there are no more pages to load and
/// pagination will not be triggered.
public readonly bool? isLastPage;
/// Used for pagination (infinite scroll) together with [onEndReached].
/// When true, indicates that there are no more pages to load and
/// pagination will not be triggered.
public readonly bool? isLastPage;
/// Item builder
public readonly ItemBuilder itemBuilder;

}
/// [ChatList] widget state
public class _ChatListState : SingleTickerProviderStateMixin<ChatList>
public class _ChatListState : SingleTickerProviderStateMixin<ChatList>
public AnimationController _controller ;
public Animation<float> _animation;
private bool _isNextPageLoading;
public List<object> _oldData ;
public Animation<float> _animation;
public AnimationController _controller;
public bool _isNextPageLoading;
public List<object> _oldData;
public override void initState()
{
base.initState();

curve: Curves.easeOutQuad,
parent: _controller
);
_isNextPageLoading = false;
_oldData = new List<object>();
_oldData.AddRange(widget.items);
}

private void _calculateDiffs(List<object> oldList)
{
_oldData = new List<object>(widget.items);
/*var diffResult = calculateListDiff<object>(
oldList,
widget.items,
equalityChecker: (item1, item2) =>
{
if (item1 is Dictionary<string, object> && item2 is Dictionary<string, object>)
{
var message1 = item1["message"]! as ChatComponents.Message;
var message2 = item2["message"]! as ChatComponents.Message;
return message1.id == message2.id;
}
return item1 == item2;
}
);
foreach (var update in diffResult.getUpdates(batch: false))
update.when(
insert: (pos, count) => { _listKey.currentState?.insertItem(pos); },
remove: (pos, count) =>
{
var item = oldList[pos];
_listKey.currentState?.removeItem(
pos,
(_, animation) => _buildRemovedMessage(item, animation)
);
},
change: (pos, payload) => { },
move: (from, to) => { }
);
foreach (var item1 in widget.items)
{
if (item1 is Dictionary<string, object> )
{
var message1 = ((Dictionary<string, object>)item1)["message"] as ChatComponents.Message;
if(message1!=null)
_listKey.currentState?.insertItem(0);
}
}
foreach (var item1 in oldList)
{
foreach (var item2 in widget.items)
{
if (item1 is Dictionary<string, object> && item2 is Dictionary<string, object>)
{
var message1 = ((Dictionary<string, object>)item1)["message"]! as ChatComponents.Message;
var message2 = ((Dictionary<string, object>)item2)["message"]! as ChatComponents.Message;
return message1.id == message2.id;
}
return item1 == item2;
}
}
}*/
// Hacky solution to reconsider
private void _scrollToBottomIfNeeded(List<object> oldList)

{
if (widget.onEndReached == null || widget.isLastPage == true) return false;
if (notification.metrics.pixels >=
notification.metrics.maxScrollExtent *
(widget.onEndReachedThreshold ?? 0.75))
var _onEndReachedThreshold =
widget.onEndReachedThreshold == null ? 0.75f : (float) widget.onEndReachedThreshold;
if (notification.metrics.pixels >= notification.metrics.maxScrollExtent * _onEndReachedThreshold)
if (widget.items.isEmpty() || _isNextPageLoading) return false;
if (widget.items.isEmpty() || _isNextPageLoading)
return false;
_controller.duration = new TimeSpan();
_controller.forward();
SchedulerBinding.instance.addPostFrameCallback(stamp =>
{
_controller.duration = TimeSpan.Zero;
_controller.forward();
setState(() => { _isNextPageLoading = true; });
setState(() => { _isNextPageLoading = true; });
widget.onEndReached().whenComplete(() =>
{
_controller.duration = TimeSpan.FromMilliseconds(300);
_controller.reverse();
setState(() => { _isNextPageLoading = false; });
widget.onEndReached().whenComplete(() =>
{
_controller.duration = TimeSpan.FromMilliseconds(300);
_controller.reverse();
setState(() => { _isNextPageLoading = false; });
});
});
}

initialItemCount: widget.items.Count,
key: _listKey,
itemBuilder: (_, index, animation) =>
_buildNewMessage(index, animation)
{
return _buildNewMessage(index, animation);
}
)
),
new SliverPadding(

正在加载...
取消
保存