欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

UGUI輪播圖組件實(shí)現(xiàn)方法詳解

 更新時(shí)間:2019年03月01日 10:22:23   作者:阿循  
這篇文章主要為大家詳細(xì)介紹了UGUI輪播圖組件的實(shí)現(xiàn)方法,支持自動(dòng)輪播、手勢(shì)切換等功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了UGUI輪播圖組件實(shí)現(xiàn)的具體代碼,供大家參考,具體內(nèi)容如下

要用到,于是就自已做了一個(gè),自認(rèn)為封裝上還是OK的,開(kāi)發(fā)于unity5.1.2。

支持自動(dòng)輪播、手勢(shì)切換、代碼調(diào)用切換,支持水平和豎直兩個(gè)方向以及正負(fù)方向輪播,輪播索引改變有回調(diào)可以用,也可以獲取到當(dāng)前處于正中的子元素。

要注意的是,向輪播列表中加入新元素不能直接setparent,要調(diào)用該組件的AddChild方法

下面是鄙人的代碼:

/// 主要關(guān)注屬性、事件及函數(shù):
///  public int CurrentIndex;
///  public Action<int> OnIndexChange;
///  public virtual void MoveToIndex(int ind);
///  public virtual void AddChild(RectTransform t);
/// by yangxun
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
/// <summary>
/// 輪播圖組件
/// </summary>
[RequireComponent(typeof(RectTransform)), ExecuteInEditMode]
public class Carousel : UIBehaviour, IEventSystemHandler, IBeginDragHandler, IInitializePotentialDragHandler, IDragHandler, IEndDragHandler, ICanvasElement {
 
 /// <summary>
 /// 子物體size
 /// </summary>
 public Vector2 CellSize;
 /// <summary>
 /// 子物體間隔
 /// </summary>
 public Vector2 Spacing;
 /// <summary>
 /// 方向
 /// </summary>
 public Axis MoveAxis;
 /// <summary>
 /// Tween時(shí)的步數(shù)
 /// </summary>
 public int TweenStepCount = 10;
 /// <summary>
 /// 自動(dòng)輪播
 /// </summary>
 public bool AutoLoop = false;
 /// <summary>
 /// 輪播間隔
 /// </summary>
 public float LoopSpace = 1;
 /// <summary>
 /// 輪播方向--1為向左移動(dòng),-1為向右移動(dòng)
 /// </summary>
 public int LoopDir = 1;
 /// <summary>
 /// 可否拖動(dòng)
 /// </summary>
 public bool Drag = true;
 /// <summary>
 /// 位于正中的子元素變化的事件,參數(shù)為index
 /// </summary>
 public Action<int> OnIndexChange;
 /// <summary>
 /// 當(dāng)前處于正中的元素
 /// </summary>
 public int CurrentIndex {
  get {
   return m_index;
  }
 }
 
 private bool m_Dragging = false;
 private bool m_IsNormalizing = false;
 private Vector2 m_CurrentPos;
 private int m_currentStep = 0;
 private RectTransform viewRectTran;
 private Vector2 m_PrePos;
 private int m_index = 0,m_preIndex = 0;
 private RectTransform header;
 private bool contentCheckCache = true;
 
 private float currTimeDelta = 0;
 private float viewRectXMin {
  get{
   Vector3[] v = new Vector3[4];
   viewRectTran.GetWorldCorners(v);
   return v[0].x;
  }
 }
 private float viewRectXMax {
  get {
   Vector3[] v = new Vector3[4];
   viewRectTran.GetWorldCorners(v);
   return v[3].x;
  }
 }
 private float viewRectYMin {
  get {
   Vector3[] v = new Vector3[4];
   viewRectTran.GetWorldCorners(v);
   return v[0].y;
  }
 }
 private float viewRectYMax {
  get {
   Vector3[] v = new Vector3[4];
   viewRectTran.GetWorldCorners(v);
   return v[2].y;
  }
 }
 
 public int CellCount {
  get {
   return transform.childCount;
  }
 }
 protected override void Awake() {
  base.Awake();
  viewRectTran = GetComponent<RectTransform>();
  header = GetChild(viewRectTran, 0);
 }
 public void resizeChildren() {
  //init child size and pos
  Vector2 delta;
  if (MoveAxis == Axis.Horizontal) {
   delta = new Vector2(CellSize.x + Spacing.x, 0);
  }
  else {
   delta = new Vector2(0, CellSize.y + Spacing.y);
  }
  for (int i = 0; i < CellCount; i++) {
   var t = GetChild(viewRectTran, i);
   if (t) {
    t.localPosition = delta * i;
    t.sizeDelta = CellSize;
   }
  }
  m_IsNormalizing = false;
  m_CurrentPos = Vector2.zero;
  m_currentStep = 0;
 }
 /// <summary>
 /// 加子物體到當(dāng)前列表的最后面
 /// </summary>
 /// <param name="t"></param>
 public virtual void AddChild(RectTransform t) {
  if (t!=null) {
   t.SetParent(viewRectTran, false);
   t.SetAsLastSibling();
   Vector2 delta;
   if (MoveAxis == Axis.Horizontal) {
    delta = new Vector2(CellSize.x + Spacing.x, 0);
   }
   else {
    delta = new Vector2(0, CellSize.y + Spacing.y);
   }
   if (CellCount == 0) {
    t.localPosition = Vector3.zero;
    header = t;
   }
   else {
    t.localPosition = delta + (Vector2)GetChild(viewRectTran,CellCount-1).localPosition;
   }
  }
 }
 protected override void OnEnable() {
  base.OnEnable();
  resizeChildren();
  return;
  if (Application.isPlaying) {
   if (ContentIsLongerThanRect()) {
    int s;
    do {
     s = GetBoundaryState();
     LoopCell(s);
    } while (s != 0);
   }
  }
 }
 protected virtual void Update() {
  if (ContentIsLongerThanRect()) {
   //實(shí)現(xiàn)在必要時(shí)loop子元素
   if (Application.isPlaying) {
    int s = GetBoundaryState();
    LoopCell(s);
   }
   //緩動(dòng)回指定位置
   if (m_IsNormalizing && EnsureListCanAdjust()) {
    if (m_currentStep == TweenStepCount) {
     m_IsNormalizing = false;
     m_currentStep = 0;
     m_CurrentPos = Vector2.zero;
     return;
    }
    Vector2 delta = m_CurrentPos/TweenStepCount;
    m_currentStep++;
    TweenToCorrect(-delta);
   }
   //自動(dòng)loop
   if (AutoLoop && !m_IsNormalizing && EnsureListCanAdjust()) {
    currTimeDelta += Time.deltaTime;
    if (currTimeDelta>LoopSpace) {
     currTimeDelta = 0;
     MoveToIndex(m_index + LoopDir);
    }
   }
   //檢測(cè)index是否變化
   if (MoveAxis == Axis.Horizontal) {
    m_index = (int)(header.localPosition.x / (CellSize.x + Spacing.x-1));
   }
   else {
    m_index = (int)(header.localPosition.y / (CellSize.y + Spacing.y-1));
   }
   if (m_index<=0) {
    m_index = Mathf.Abs(m_index);
   }
   else {
    m_index = CellCount - m_index;
   }
   if (m_index != m_preIndex) {
    if (OnIndexChange != null) {
     OnIndexChange(m_index);
    }
   }
   m_preIndex = m_index;
  }
 }
 public virtual void OnBeginDrag(PointerEventData eventData) {
  if (!Drag || !contentCheckCache) {
   return;
  }
  Vector2 vector;
  if (((eventData.button == PointerEventData.InputButton.Left) && this.IsActive()) && RectTransformUtility.ScreenPointToLocalPointInRectangle(this.viewRectTran, eventData.position, eventData.pressEventCamera, out vector)) {
   this.m_Dragging = true;
   m_PrePos = vector;
  }
 }
 
 public virtual void OnInitializePotentialDrag(PointerEventData eventData) {
  if (!Drag) {
   return;
  }
  return;
 }
 
 public virtual void OnDrag(PointerEventData eventData) {
  if (!Drag || !contentCheckCache) {
   return;
  }
  Vector2 vector;
  if (((eventData.button == PointerEventData.InputButton.Left) && this.IsActive()) && RectTransformUtility.ScreenPointToLocalPointInRectangle(this.viewRectTran, eventData.position, eventData.pressEventCamera, out vector)) {
   m_IsNormalizing = false;
   m_CurrentPos = Vector2.zero;
   m_currentStep = 0;
   Vector2 vector2 = vector - this.m_PrePos;
   Vector2 vec = CalculateOffset(vector2);
   this.SetContentPosition(vec);
   m_PrePos = vector;
  }
 }
 /// <summary>
 /// 移動(dòng)到指定索引
 /// </summary>
 /// <param name="ind"></param>
 public virtual void MoveToIndex(int ind) {
  if (m_IsNormalizing) {
   return;
  }
  //Debug.LogFormat("{0}->{1}",m_index,ind);
  if (ind == m_index) {
   return;
  }
  this.m_IsNormalizing = true;
  Vector2 offset;
  if (MoveAxis == Axis.Horizontal) {
   offset = new Vector2(CellSize.x + Spacing.x, 0);
  }
  else {
   offset = new Vector2(0, CellSize.y + Spacing.y);
  }
  var delta = CalcCorrectDeltaPos();
  int vindex = m_index;
  m_CurrentPos = delta + offset * (ind - vindex);
  //m_CurrentPos = -(Vector2)header.localPosition + offset * (ind - m_index);
  m_currentStep = 0;
 }
 private Vector2 CalculateOffset(Vector2 delta) {
  if (MoveAxis == Axis.Horizontal) {
   delta.y = 0;
  }
  else {
   delta.x = 0;
  }
  return delta;
 }
 private void SetContentPosition(Vector2 position) {
  foreach (RectTransform i in viewRectTran) {
   i.localPosition += (Vector3)position;
  }
  return;
 }
 
 public virtual void OnEndDrag(PointerEventData eventData) {
  if (!Drag || !contentCheckCache) {
   return;
  }
  this.m_Dragging = false;
  this.m_IsNormalizing = true;
  m_CurrentPos = CalcCorrectDeltaPos();
  m_currentStep = 0;
 }
 
 public virtual void Rebuild(CanvasUpdate executing) {
  return;
 }
 /// <summary>
 /// List是否處于可自由調(diào)整狀態(tài)
 /// </summary>
 /// <returns></returns>
 public virtual bool EnsureListCanAdjust() {
  return !m_Dragging && ContentIsLongerThanRect();
 }
 /// <summary>
 /// 內(nèi)容是否比顯示范圍大
 /// </summary>
 /// <returns></returns>
 public virtual bool ContentIsLongerThanRect() {
  float contentLen;
  float rectLen;
  if (MoveAxis == Axis.Horizontal) {
   contentLen = CellCount*(CellSize.x + Spacing.x) - Spacing.x;
   rectLen = viewRectTran.rect.xMax - viewRectTran.rect.xMin;
  }
  else {
   contentLen = CellCount * (CellSize.y + Spacing.y) - Spacing.y;
   rectLen = viewRectTran.rect.yMax - viewRectTran.rect.yMin;
  }
  contentCheckCache = contentLen > rectLen;
  return contentCheckCache;
 }
 /// <summary>
 /// 檢測(cè)邊界情況,分為0未觸界,-1左(下)觸界,1右(上)觸界
 /// </summary>
 /// <returns></returns>
 public virtual int GetBoundaryState() {
  RectTransform left;
  RectTransform right;
  left = GetChild(viewRectTran, 0);
  right = GetChild(viewRectTran, CellCount - 1);
  Vector3[] l = new Vector3[4];
  left.GetWorldCorners(l);
  Vector3[] r = new Vector3[4];
  right.GetWorldCorners(r);
  if (MoveAxis == Axis.Horizontal) {
   if (l[0].x>=viewRectXMin) {
    return -1;
   }
   else if (r[3].x < viewRectXMax) {
    return 1;
   }
  }
  else {
   if (l[0].y >= viewRectYMin) {
    return -1;
   }
   else if (r[1].y < viewRectYMax) {
    return 1;
   }
  }
  return 0;
 }
 /// <summary>
 /// Loop列表,分為-1把最右(上)邊一個(gè)移到最左(下)邊,1把最左(下)邊一個(gè)移到最右(上)邊
 /// </summary>
 /// <param name="dir"></param>
 protected virtual void LoopCell(int dir) {
  if (dir == 0) {
   return;
  }
  RectTransform MoveCell;
  RectTransform Tarborder;
  Vector2 TarPos;
  if (dir == 1) {
   MoveCell = GetChild(viewRectTran, 0);
   Tarborder = GetChild(viewRectTran, CellCount - 1);
   MoveCell.SetSiblingIndex(CellCount-1);
  }
  else {
   Tarborder = GetChild(viewRectTran, 0);
   MoveCell = GetChild(viewRectTran, CellCount - 1);
   MoveCell.SetSiblingIndex(0);
  }
  if (MoveAxis == Axis.Horizontal) {
   TarPos = Tarborder.localPosition + new Vector3((CellSize.x + Spacing.x) * dir, 0,0);
  }
  else {
   TarPos = (Vector2)Tarborder.localPosition + new Vector2(0, (CellSize.y + Spacing.y) * dir);
  }
  MoveCell.localPosition = TarPos;
 }
 /// <summary>
 /// 計(jì)算一個(gè)最近的正確位置
 /// </summary>
 /// <returns></returns>
 public virtual Vector2 CalcCorrectDeltaPos() {
  Vector2 delta = Vector2.zero;
  float distance = float.MaxValue;
  foreach (RectTransform i in viewRectTran) {
   var td = Mathf.Abs(i.localPosition.x) + Mathf.Abs(i.localPosition.y);
   if (td<=distance) {
    distance = td;
    delta = i.localPosition;
   }
   else {
    break;
   }
  }
  return delta;
 }
 /// <summary>
 /// 移動(dòng)指定增量
 /// </summary>
 protected virtual void TweenToCorrect(Vector2 delta) {
  foreach (RectTransform i in viewRectTran) {
   i.localPosition += (Vector3)delta;
  }
 }
 public enum Axis {
  Horizontal,
  Vertical
 }
 private static RectTransform GetChild(RectTransform parent, int index) {
  if (parent == null||index>=parent.childCount) {
   return null;
  }
  return parent.GetChild(index) as RectTransform;
 }
}

用法和ugui的scrollrect組件是差不多的,因?yàn)楸緛?lái)在drag事件上有所借鑒
例圖如下:

另外,它不會(huì)像ugui的幾個(gè)布局組件一樣自動(dòng)去改變子元素的大小為cellsize,cellsize只是虛擬的子元素容器大小,這個(gè)要注意下。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關(guān)文章

  • WPF+SkiaSharp實(shí)現(xiàn)自繪拖曳小球

    WPF+SkiaSharp實(shí)現(xiàn)自繪拖曳小球

    WPF的拖曳效果,基本配置一下,就可以了,但是自繪的話,就得自己控制。本文將利用WPF+SkiaSharp實(shí)現(xiàn)自繪拖曳小球,感興趣的可以動(dòng)手嘗試一下
    2022-07-07
  • 超炫酷的WPF實(shí)現(xiàn)Loading控件效果

    超炫酷的WPF實(shí)現(xiàn)Loading控件效果

    這篇文章主要介紹了超炫酷的WPF實(shí)現(xiàn)Loading控件效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2015-11-11
  • C# 使用Serilog日志框架的方法

    C# 使用Serilog日志框架的方法

    Serilog是一款配置方便,使用靈活的日志框架,這篇文章主要介紹了C# 使用Serilog日志框架,需要的朋友可以參考下
    2023-11-11
  • Unity3D實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲(2)

    Unity3D實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲(2)

    這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲的第二部分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • C#實(shí)現(xiàn)軟件監(jiān)控外部程序運(yùn)行狀態(tài)的方法

    C#實(shí)現(xiàn)軟件監(jiān)控外部程序運(yùn)行狀態(tài)的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)軟件監(jiān)控外部程序運(yùn)行狀態(tài)的方法,可實(shí)現(xiàn)監(jiān)控另一個(gè)程序的運(yùn)行狀態(tài)及觸發(fā)相應(yīng)事件的功能,是非常實(shí)用的技巧,需要的朋友可以參考下
    2014-12-12
  • C#實(shí)現(xiàn)Redis的分布式鎖

    C#實(shí)現(xiàn)Redis的分布式鎖

    我們?cè)陂_(kāi)發(fā)很多業(yè)務(wù)場(chǎng)景會(huì)使用到鎖,例如庫(kù)存控制,抽獎(jiǎng)等。分布式與單機(jī)情況下最大的不同在于其不是多線程而是多進(jìn)程。本文就來(lái)介紹一下,感興趣的可以了解一下
    2021-08-08
  • win7中C#的winForm編程使用savefiledialog不能彈出保存窗體的解決方法

    win7中C#的winForm編程使用savefiledialog不能彈出保存窗體的解決方法

    這篇文章主要介紹了win7中C#的winForm編程使用savefiledialog不能彈出保存窗體的解決方法,涉及針對(duì)線程的調(diào)用問(wèn)題,是比較實(shí)用的技巧,需要的朋友可以參考下
    2014-12-12
  • C#區(qū)分中英文按照指定長(zhǎng)度截取字符串的方法

    C#區(qū)分中英文按照指定長(zhǎng)度截取字符串的方法

    這篇文章主要介紹了C#區(qū)分中英文按照指定長(zhǎng)度截取字符串的方法,涉及C#操作字符串的正則匹配與截取等常用操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-03-03
  • c#生成隨機(jī)數(shù)示例分享

    c#生成隨機(jī)數(shù)示例分享

    這篇文章主要介紹了c#生成隨機(jī)數(shù)示例分享,需要的朋友可以參考下
    2014-03-03
  • C#的winform控件命名規(guī)范

    C#的winform控件命名規(guī)范

    這篇文章主要介紹了C#的winform控件命名規(guī)范,對(duì)各種常用控件的命名規(guī)范做了較為詳細(xì)的講解,需要的朋友可以參考下
    2015-01-01

最新評(píng)論