やりたいこと
-
ScrollView内のコンテンツの一番下にアイテムが追加された時、一番下にスクロールバーを下げたい。
-
コマンドライン風UI作ってる時にコマンドラインって画面が常時一番下にスクロールした状態になるのでこれがやりたかった。
こんな感じ
やりかた
ScrollRect.verticalNormalizedPositionってパラメータをいじる
- 0だと一番下
- 1だと一番上
ScrollView/ViewPort/Textを今回ScrollRectのContentに設定してる。
テキストにはContentSizeFilterをaddして
vertical FitをPrefferred Sizeにすることで自動で高さ調整
InputFieldにConsoleTextCoreをaddしてOnEndEditでConsoleTextCore.OnInputを呼ぶようにする。
public class ConsoleTextCore : MonoBehaviour
{
private InputField _inputField;
public Text ConsoleText;
public ScrollRect ScrollRect;
// Use this for initialization
void Start ()
{
_inputField = GetComponent<InputField>();
InitInputField();
}
// Update is called once per frame
void Update () {
}
public void OnInput()
{
string inputValue = _inputField.text;
WriteConsole(inputValue);
InitInputField();
}
void WriteConsole(string text)
{
ConsoleText.text += "\n" + text;
}
void InitInputField() {
// 値をリセット
_inputField.text = "";
// フォーカス
_inputField.ActivateInputField();
ScrollRect.verticalNormalizedPosition = 0; //ここでスクロールを一番下にする
}
}
inputfieldが入力されたらOnInput()が呼ばれ、上のコンソール風にしたテキストに表示され、一番下にスクロールするようにした。
問題点
この方がおっしゃられているのですがこれをやってもなぜか一番下にならず微妙に余った状態になってしまう。
こんな感じでスクロールバーが下に行かない
よく見てみると更新された高さ分余ってる。
これscrollviewがコンテンツの高さ更新を認識してないのかなと思ったが、そもそも高さが更新されるのがポジションをいじるのより遅いんじゃねって考えた。
要はConsoleText.textにstring足すだけだとContentSizeFilterがその変更を反映してないときにポジション変更呼んじゃってるんじゃないかと。
なのでなんか高さ更新的なメソッド無いかなぁって探したら
ContentSizeFilter.SetLayoutVertical()
ってのがあった。
めっちゃそれっぽい。
とりあえず呼んでみた。
public void WriteConsole(string text)
{
ConsoleText.text += "\n" + text;
ConsoleText.GetComponent<ContentSizeFitter>().SetLayoutVertical();//<-これ追加
}
動いた!!(再掲)
この方法があってるかわからんけど明示的に高さ更新されたよって教えてあげるとなんかうまくいった。
間違ってたらすいません。今回の場合はうまくいきました。
まとめ
- コンテントにアイテムとか追加して高さを変える
- ContentSizeFitter.SetLayoutVertical()を呼んで明示的に高さを更新してあげる
- ScrollRect.verticalNormalizedPosition = 0(一番下にスクロール位置をもってく場合)と変更する。
以上!