6-12 Finishing Login User Interface
本章要繼續完成登入畫面,接著來佈置登入按鈕的部分吧。在Loing Window按右鍵,選擇UI/Button。
預設的按鈕真的很醜。
接著自己修改背景圖片跟Text的屬性,Text的部分可以參考我的設定。
設定好以後如下圖,但仍舊覺得文字只有單一白色實在太單調,跟按鈕的配色也不太合。
這邊介紹幾個好用的Script,待會提供原始碼,Gradient.cs可以替UI元件建立漸層色,如下圖設定。
接著文字就會有漸層色了。
然後再使用NicerOutline.cs可以建立外邊框,如下圖設定。
文字的外邊框也做出來了,是否好看很多了呢。
接著替Button建立一個Image名為Press Overlay,這是我要用來自訂Button按下去時的陰影。
將陰影放進來後的結果如下圖,會將整個按鈕跟文字都蓋過去。
接著將Press Overlay拖拉進Button的Target Graphic中,並將Normal Color跟Highlighted Color的Alpha值設為0。這樣一來在普通狀態以及滑鼠移動到按鈕上的狀態,都不會將顯示這個陰影,只要按下去的時候才會出現。
設定完成如下圖。
以下提供Gradient跟NicerOutline的原始碼。
Gradient.cs:
NicerOutline.cs:
接著新增帳號跟密碼的輸入框,首先在LoginWindow底下新增Empty GameObject名為Content,然後再新增UI/Input Field。
新增InputField之後,先設定Placeholder,這個是用來顯示『提示文字』用的,設定可以參考如下圖。
接著也替該文字新增Shadow,增加立體感。
然後InputField底下的Text也記得與Placeholder使用相同設定。Text才是真正用來輸入文字的部分,輸入時InputField會自動將Placeholder上的提示文字隱藏。
設定完成後的效果應能如下圖。
接著我在InputField內在新增一個小icon。
接著我們替InputField新增一個Focus Overlay的Image吧,當使用者輸入文字的時候,框框的邊緣會有高亮效果。
新增的效果如下圖。
記得將Focus Overlay拖拉進Target Graphic中,並將Normal Color的Alpha值設為0,基本上設定手法與Button差不多。
這樣的話平時的InputField如下圖。
開始輸入文字的時候就會自動有發光的邊緣了。
然後讓我們把這個設定好的InputField直接Duplicate吧。
由於密碼框的輸入需要使用*字號隱藏,請在InputField的Content Type設定中選擇Password,即可達到這個效果。
剩下這個就自行調整吧,調整好如下圖。
可以使用我上一章提供的UIFlippable.cs將密碼框水平反轉,效果更好看。登入介面完成!
預設的按鈕真的很醜。
接著自己修改背景圖片跟Text的屬性,Text的部分可以參考我的設定。
設定好以後如下圖,但仍舊覺得文字只有單一白色實在太單調,跟按鈕的配色也不太合。
這邊介紹幾個好用的Script,待會提供原始碼,Gradient.cs可以替UI元件建立漸層色,如下圖設定。
接著文字就會有漸層色了。
然後再使用NicerOutline.cs可以建立外邊框,如下圖設定。
文字的外邊框也做出來了,是否好看很多了呢。
接著替Button建立一個Image名為Press Overlay,這是我要用來自訂Button按下去時的陰影。
接著將Press Overlay拖拉進Button的Target Graphic中,並將Normal Color跟Highlighted Color的Alpha值設為0。這樣一來在普通狀態以及滑鼠移動到按鈕上的狀態,都不會將顯示這個陰影,只要按下去的時候才會出現。
設定完成如下圖。
以下提供Gradient跟NicerOutline的原始碼。
Gradient.cs:
using UnityEngine; using System.Collections.Generic; namespace UnityEngine.UI { [AddComponentMenu("UI/Effects/Gradient")] #if UNITY_5_2 || UNITY_5_3_OR_NEWER public class Gradient : BaseMeshEffect #else public class Gradient : BaseVertexEffect #endif { [SerializeField] private Color topColor = Color.white; [SerializeField] private Color bottomColor = Color.black; #if UNITY_5_2 || UNITY_5_3_OR_NEWER public override void ModifyMesh(VertexHelper vertexHelper) { if (!this.IsActive()) return; Listlist = new List (); vertexHelper.GetUIVertexStream(list); ModifyVertices(list); // calls the old ModifyVertices which was used on pre 5.2 vertexHelper.Clear(); vertexHelper.AddUIVertexTriangleStream(list); } #endif #if UNITY_5_2 || UNITY_5_3_OR_NEWER public void ModifyVertices(List vertexList) #else public override void ModifyVertices(List vertexList) #endif { if (!this.IsActive()) return; int count = vertexList.Count; float bottomY = vertexList[0].position.y; float topY = vertexList[0].position.y; for (int i = 1; i < count; i++) { float y = vertexList[i].position.y; if (y > topY) { topY = y; } else if (y < bottomY) { bottomY = y; } } float uiElementHeight = topY - bottomY; for (int i = 0; i < count; i++) { UIVertex uiVertex = vertexList[i]; uiVertex.color = uiVertex.color * Color.Lerp(bottomColor, topColor, (uiVertex.position.y - bottomY) / uiElementHeight); vertexList[i] = uiVertex; } } } }
NicerOutline.cs:
/// Credit Melang /// Sourced from - http://forum.unity3d.com/members/melang.593409/ using System.Collections.Generic; namespace UnityEngine.UI { [AddComponentMenu("UI/Effects/Nicer Outline")] #if UNITY_5_2 || UNITY_5_3_OR_NEWER public class NicerOutline : BaseMeshEffect #else public class NicerOutline : BaseVertexEffect #endif { [SerializeField] private Color m_EffectColor = new Color (0f, 0f, 0f, 0.5f); [SerializeField] private Vector2 m_EffectDistance = new Vector2 (1f, -1f); [SerializeField] private bool m_UseGraphicAlpha = true; // // Properties // public Color effectColor { get { return this.m_EffectColor; } set { this.m_EffectColor = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } public Vector2 effectDistance { get { return this.m_EffectDistance; } set { if (value.x > 600f) { value.x = 600f; } if (value.x < -600f) { value.x = -600f; } if (value.y > 600f) { value.y = 600f; } if (value.y < -600f) { value.y = -600f; } if (this.m_EffectDistance == value) { return; } this.m_EffectDistance = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } public bool useGraphicAlpha { get { return this.m_UseGraphicAlpha; } set { this.m_UseGraphicAlpha = value; if (base.graphic != null) { base.graphic.SetVerticesDirty (); } } } #if UNITY_EDITOR protected override void OnValidate () { this.effectDistance = this.m_EffectDistance; base.OnValidate (); } #endif // // Methods // protected void ApplyShadow (Listverts, Color32 color, int start, int end, float x, float y) { //Debug.Log("verts count: "+verts.Count); int num = verts.Count * 2; if (verts.Capacity < num) { verts.Capacity = num; } for (int i = start; i < end; i++) { UIVertex uIVertex = verts [i]; verts.Add (uIVertex); Vector3 position = uIVertex.position; //Debug.Log("vertex pos: "+position); position.x += x; position.y += y; uIVertex.position = position; Color32 color2 = color; if (this.m_UseGraphicAlpha) { color2.a = (byte)(color2.a * verts [i].color.a / 255); } uIVertex.color = color2; //uIVertex.color = (Color32)Color.blue; verts [i] = uIVertex; } } #if UNITY_5_2 || UNITY_5_3_OR_NEWER public override void ModifyMesh(VertexHelper vertexHelper) { if (!this.IsActive()) return; List list = new List (); vertexHelper.GetUIVertexStream(list); ModifyVertices(list); // calls the old ModifyVertices which was used on pre 5.2 vertexHelper.Clear(); vertexHelper.AddUIVertexTriangleStream(list); } #endif #if UNITY_5_2 || UNITY_5_3_OR_NEWER public void ModifyVertices(List verts) #else public override void ModifyVertices(List verts) #endif { if (!this.IsActive ()) { return; } Text foundtext = GetComponent (); float best_fit_adjustment = 1f; if (foundtext && foundtext.resizeTextForBestFit) { best_fit_adjustment = (float)foundtext.cachedTextGenerator.fontSizeUsedForBestFit / (foundtext.resizeTextMaxSize-1); //max size seems to be exclusive } float distanceX = this.effectDistance.x * best_fit_adjustment; float distanceY = this.effectDistance.y * best_fit_adjustment; int start = 0; int count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, distanceY); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, -distanceY); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, distanceY); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, -distanceY); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, distanceX, 0); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, -distanceX, 0); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, 0, distanceY); start = count; count = verts.Count; this.ApplyShadow (verts, this.effectColor, start, verts.Count, 0, -distanceY); } } }
接著新增帳號跟密碼的輸入框,首先在LoginWindow底下新增Empty GameObject名為Content,然後再新增UI/Input Field。
接著也替該文字新增Shadow,增加立體感。
然後InputField底下的Text也記得與Placeholder使用相同設定。Text才是真正用來輸入文字的部分,輸入時InputField會自動將Placeholder上的提示文字隱藏。
設定完成後的效果應能如下圖。
接著我在InputField內在新增一個小icon。
接著我們替InputField新增一個Focus Overlay的Image吧,當使用者輸入文字的時候,框框的邊緣會有高亮效果。
新增的效果如下圖。
記得將Focus Overlay拖拉進Target Graphic中,並將Normal Color的Alpha值設為0,基本上設定手法與Button差不多。
這樣的話平時的InputField如下圖。
開始輸入文字的時候就會自動有發光的邊緣了。
然後讓我們把這個設定好的InputField直接Duplicate吧。
由於密碼框的輸入需要使用*字號隱藏,請在InputField的Content Type設定中選擇Password,即可達到這個效果。
剩下這個就自行調整吧,調整好如下圖。
可以使用我上一章提供的UIFlippable.cs將密碼框水平反轉,效果更好看。登入介面完成!
留言
張貼留言