You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

311 lines
12 KiB

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using EnhancedUI;
using EnhancedUI.EnhancedScroller;
namespace EnhancedScrollerDemos.Chat
{
/// <summary>
/// Simple example of one way a chat scroller could look
/// </summary>
public class Chat : MonoBehaviour, IEnhancedScrollerDelegate
{
/// <summary>
/// Internal representation of our data. Note that the scroller will never see
/// this, so it separates the data from the layout using MVC principles.
/// </summary>
private List<Data> _data;
/// <summary>
/// This stores the total size of all the cells,
/// plus the scroller's top and bottom padding.
/// This will be used to calculate the spacer required
/// </summary>
private float _totalCellSize = 0;
/// <summary>
/// Stores the scroller's position before jumping to the new chat cell
/// </summary>
private float _oldScrollPosition = 0;
/// <summary>
/// This is our scroller we will be a delegate for
/// </summary>
public EnhancedScroller scroller;
/// <summary>
/// The input field for texts from us
/// </summary>
public UnityEngine.UI.InputField myInputField;
/// <summary>
/// The input field for simulated texts from another person
/// </summary>
public UnityEngine.UI.InputField otherInputField;
/// <summary>
/// This will be the prefab of our chat cell
/// </summary>
public EnhancedScrollerCellView myTextCellViewPrefab;
/// <summary>
/// This will be the prefab of another person's chat cell
/// </summary>
public EnhancedScrollerCellView otherTextCellViewPrefab;
/// <summary>
/// This will be the prefab of our first cell to push the other cells to the bottom
/// </summary>
public EnhancedScrollerCellView spacerCellViewPrefab;
/// <summary>
/// The estimated width of each character. Note that this is just an estimate
/// since most fonts are not mono-spaced.
/// </summary>
public int characterWidth = 8;
/// <summary>
/// The height of each character.
/// </summary>
public int characterHeight = 26;
void Start()
{
// set the application frame rate.
// this improves smoothness on some devices
Application.targetFrameRate = 60;
// tell the scroller that this script will be its delegate
scroller.Delegate = this;
// set up a single data item containing the spacer
// this pushes the cells down to the bottom
_data = new List<Data>();
_data.Add(new Data() { cellType = Data.CellType.Spacer });
// call resize scroller to calculate and set up the scroll
ResizeScroller();
// focus on the chat input field
myInputField.ActivateInputField();
}
/// <summary>
/// Called every frame to check for return key presses.
/// A return key press will send the chat
/// </summary>
void Update()
{
if (Input.GetKeyDown(KeyCode.Return))
{
if (myInputField.isFocused)
{
SendButton_Click();
}
else if (otherInputField.isFocused)
{
OtherSendButton_Click();
}
}
}
/// <summary>
/// This function adds a new record, resizing the scroller and calculating the sizes of all cells
/// </summary>
public void AddNewRow(Data.CellType cellType, string text)
{
// first, clear out the cells in the scroller so the new text transforms will be reset
scroller.ClearAll();
_oldScrollPosition = scroller.ScrollPosition;
// reset the scroller's position so that it is not outside of the new bounds
scroller.ScrollPosition = 0;
// calculate the space needed for the text in the cell
// get the estimated total width of the text (estimated because the font is assumed to be mono-spaced)
float totalTextWidth = (float)text.Length * (float)characterWidth;
// get the number of rows the text will take up by dividing the total width by the widht of the cell
int numRows = Mathf.CeilToInt(totalTextWidth / scroller.GetComponent<RectTransform>().sizeDelta.x) + 1;
// get the cell size by multiplying the rows times the character height
var cellSize = numRows * (float)characterHeight;
// now we can add the data row
_data.Add(new Data()
{
cellType = cellType,
cellSize = cellSize,
someText = text
});
ResizeScroller();
// jump to the end of the scroller to see the new content.
// once the jump is completed, reset the spacer's size
scroller.JumpToDataIndex(_data.Count - 1, 1f, 1f, tweenType: EnhancedScroller.TweenType.easeInOutSine, tweenTime: 0.5f, jumpComplete: ResetSpacer);
}
/// <summary>
/// This function will expand the scroller to accommodate the cells, reload the data to calculate the cell sizes,
/// reset the scroller's size back, then reload the data once more to display the cells.
/// </summary>
private void ResizeScroller()
{
// capture the scroll rect size.
// this will be used at the end of this method to determine the final scroll position
var scrollRectSize = scroller.ScrollRectSize;
// capture the scroller's position so we can smoothly scroll from it to the new cell
var offset = _oldScrollPosition - scroller.ScrollSize;
// capture the scroller dimensions so that we can reset them when we are done
var rectTransform = scroller.GetComponent<RectTransform>();
var size = rectTransform.sizeDelta;
// set the dimensions to the largest size possible to acommodate all the cells
rectTransform.sizeDelta = new Vector2(size.x, float.MaxValue);
// calculate the total size required by all cells. This will be used when we determine
// where to end up at after we reload the data on the second pass.
_totalCellSize = scroller.padding.top + scroller.padding.bottom;
for (var i = 1; i < _data.Count; i++)
{
_totalCellSize += _data[i].cellSize + (i < _data.Count - 1 ? scroller.spacing : 0);
}
// set the spacer to the entire scroller size.
// this is necessary because we need some space to actually do a jump
_data[0].cellSize = scrollRectSize;
// reset the scroller size back to what it was originally
rectTransform.sizeDelta = size;
// reload the data with the newly set cell view sizes and scroller content size.
//_calculateLayout = false;
scroller.ReloadData();
// set the scroll position to the previous cell (plus the offset of where the scroller currently is) so that we can jump to the new cell.
scroller.ScrollPosition = (_totalCellSize - _data[_data.Count - 1].cellSize) + offset;
}
/// <summary>
/// This method is called when the new cell has been jumpped to.
/// It will reset the spacer's cell size to the remainder of the scroller's size minus the
/// total cell size calculated in ResizeScroller. Finally, it will reload the
/// scroller to set the new cell sizes.
/// </summary>
private void ResetSpacer()
{
// reset the spacer's cell size to the scroller's size minus the rest of the cell sizes
// (or zero if the spacer is no longer needed)
_data[0].cellSize = Mathf.Max(scroller.ScrollRectSize - _totalCellSize, 0);
// reload the data to set the new cell size
scroller.ReloadData(1.0f);
}
#region UI Handlers
/// <summary>
/// Button handler sending message
/// </summary>
public void SendButton_Click()
{
// add a chat row from us
AddNewRow(Data.CellType.MyText, myInputField.text);
// clear the input field and focus on it
myInputField.text = "";
myInputField.ActivateInputField();
}
/// <summary>
/// Button handler sending other person's message
/// </summary>
public void OtherSendButton_Click()
{
// add a chat row from another person
AddNewRow(Data.CellType.OtherText, otherInputField.text);
// clear the input field and focus on it
otherInputField.text = "";
otherInputField.ActivateInputField();
}
#endregion
#region EnhancedScroller Handlers
/// <summary>
/// This tells the scroller the number of cells that should have room allocated. This should be the length of your data array.
/// </summary>
/// <param name="scroller">The scroller that is requesting the data size</param>
/// <returns>The number of cells</returns>
public int GetNumberOfCells(EnhancedScroller scroller)
{
// in this example, we just pass the number of our data elements
return _data.Count;
}
/// <summary>
/// Gets the cell view size for each cell
/// </summary>
/// <param name="scroller"></param>
/// <param name="dataIndex"></param>
/// <returns></returns>
public float GetCellViewSize(EnhancedScroller scroller, int dataIndex)
{
// return the cell size for each cell
return _data[dataIndex].cellSize;
}
/// <summary>
/// Reuse the appropriate cell
/// </summary>
/// <param name="scroller"></param>
/// <param name="dataIndex"></param>
/// <param name="cellIndex"></param>
/// <returns></returns>
public EnhancedScrollerCellView GetCellView(EnhancedScroller scroller, int dataIndex, int cellIndex)
{
CellView cellView;
if (dataIndex == 0)
{
// this is the first spacer cell
cellView = scroller.GetCellView(spacerCellViewPrefab) as CellView;
cellView.name = "Spacer";
}
else
{
// this is a chat cell
if (_data[dataIndex].cellType == Data.CellType.MyText)
{
// this is one of our chat cells
cellView = scroller.GetCellView(myTextCellViewPrefab) as CellView;
}
else
{
// this is a chat cell from another person
cellView = scroller.GetCellView(otherTextCellViewPrefab) as CellView;
}
// set the cell's game object name. Not necessary, but nice for debugging.
cellView.name = "Cell " + dataIndex.ToString();
// initialize the cell's data so that it can configure its view.
cellView.SetData(_data[dataIndex]);
}
return cellView;
}
#endregion
}
}