VB开发安卓程序_例程1调用浮动窗体类

整个工程源码已上传。


添加一个标准类模块

类模块结构

运行截图

Main模块代码

#Region Module Attributes
	#FullScreen: True
	#IncludeTitle: False
	#ApplicationLabel: Floating Window demo2
	#VersionCode: 1
	#VersionName: 
	#SupportedOrientations: unspecified
	#CanInstallToExternalStorage: False
#End Region

Sub Process_Globals
	'These global variables will be declared once when the application starts.
	'These variables can be accessed from all modules.
End Sub

Sub Globals

	'创建一个ClsFloatingWindow类对象
	Dim Win As ClsFloatingWindow
	
	'Panel是一个面板控件,主要是用来装载控件,也就是说它上面可放置很多控件
	Dim pnl(6) As Panel
	
	'标签控件
	Dim lbl As Label
	
End Sub

'Activity模块运行时先执行这个事件
Sub Activity_Create(FirstTime As Boolean)
	
'	Activity背景色设置
	Activity.Color = Colors.RGB(0, 100, 0)

'	初始化窗体对象
	Win.Initialize(Activity, 0, 0, 90dip, 90dip, Me)
	
	'设置标题栏文本
	Win.SetTitleText("Drag me")
	
	Win.StillVisible = 90dip
	
	Win.TouchSlop = 0 'The window will start to move immediately after a finger move
	
	ChangeGradient(Colors.White)

	' Docking areas and sticky edge
	Dim wRect As Rect, Left, Top, p As Int
	
	lbl.Initialize("")
	lbl.Text = "Here is a sticky area"
	lbl.TextSize = 16
	
	If Activity.Width > Activity.Height Then
		
		设置窗体显示的坐标位置
		Win.Move(100%x - 90dip, 150dip, True)
		
		For i = 0 To 1
			
			For j = 0 To 2
				
				Left = (j * 120dip) + 10dip
				Top = (i * 120dip) + 10dip
				p = (i*3)+j
				pnl(p).Initialize("")
				pnl(p).Tag = Colors.RGB(Rnd(80, 256), Rnd(80, 256), Rnd(80, 256))
				pnl(p).Color = pnl(p).Tag
				Activity.AddView(pnl(p), Left, Top, 110dip, 110dip)
				wRect.Initialize(Left, Top, Left + 110dip, Top + 110dip)
				
'				添加停靠区域
'				如果窗口进入停靠区域,则该区域将可见。
'				如果移动结束时窗口仍在该区域中,则会移动窗口并调整其大小以适应该区域。				
				Win.AddDockingArea(wRect)
				
			Next
			
		Next
		
		Win.AddStickyEdge(2, 40%x) ' The right edge is sticky
		Activity.AddView(lbl, 60%x, 10dip, 40%x, 200dip) 
		lbl.Gravity = Gravity.RIGHT
		
	Else
		
		Win.Move(200dip, 100%y - 90dip, True)
		
		For i = 0 To 2
			For j = 0 To 1
				Left = (j * 120dip) + 10dip
				Top = (i * 120dip) + 10dip
				p = (i*2)+j
				pnl(p).Initialize("")
				pnl(p).Tag = Colors.RGB(Rnd(80, 256), Rnd(80, 256), Rnd(80, 256))
				pnl(p).Color = pnl(p).Tag
				Activity.AddView(pnl(p), Left, Top, 110dip, 110dip)
				wRect.Initialize(Left, Top, Left + 110dip, Top + 110dip)
				
'				添加停靠区域
'				如果窗口进入停靠区域,则该区域将可见。
'				如果移动结束时窗口仍在该区域中,则会移动窗口并调整其大小以适应该区域。
				Win.AddDockingArea(wRect)
				
			Next
		Next
		Win.AddStickyEdge(3, 40%y) ' The bottom edge is sticky
		Activity.AddView(lbl, 10dip, 60%y, 200dip, 40%y) 
		lbl.Gravity = Gravity.BOTTOM
		
	End If
	
	Win.DockingAreaColor = Colors.Transparent
	Win.StickyAreaColor = Colors.ARGB(60, 0, 0, 128)
	Win.SetOnStickListener("After_Stick")
	Win.SetOnEnterDockAreaListener("Entering_DockA")
	Win.SetOnDockListener("After_Dock")
	Win.SetOnUndockListener("After_Undock")
	
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub After_Stick(Window As ClsFloatingWindow, Edge As Int)
	Log("Stuck ! Edge=" & Edge)
End Sub

Sub ChangeGradient(NewColor As Int)
	Dim gd As GradientDrawable
	Dim Couleurs(2) As Int
	Couleurs(0) = Colors.Black
	Couleurs(1) = NewColor
	gd.Initialize("BOTTOM_TOP", Couleurs)
	Win.SetBackground(gd)
End Sub

Sub ColorWindow(DockRect As Rect)
	' We color the window with the panel color
	For i = 0 To 5
		If pnl(i).Left = DockRect.Left And pnl(i).Top = DockRect.Top Then
			ChangeGradient(pnl(i).Tag)
			Exit
		End If
	Next
End Sub

Sub Entering_DockA(Window As ClsFloatingWindow, DockRect As Rect)
	' We color the window with the panel color
	ColorWindow(DockRect)
End Sub

Sub After_Dock(Window As ClsFloatingWindow, DockRect As Rect)
	' We change the title
	Win.SetTitleText("I'm docked")
	' We color the window with the panel color
	ColorWindow(DockRect)
End Sub

Sub After_Undock(Window As ClsFloatingWindow)
	' We return to the initial size and title
	Win.Resize(90dip, 90dip)
	Win.SetTitleText("Drag me")
	' We center the window in the docking area
	Win.Move(Win.getLeft + 10dip, Win.getTop + 10dip, True)
End Sub

类ClsFloatingWindow代码


'Class module
'Version: 1.24
Sub Class_Globals
	Public DockingAreaColor As Int
	Public StickyAreaColor As Int
	Public PinnedWindowMsg As String
	Public MinimumWidthAfterResize As Int
	Public MinimumHeightAfterResize As Int
	Public MaximumWidthAfterResize As Int
	Public MaximumHeightAfterResize As Int
	Public MinimumCoveredSurfaceForDocking As Int
	Public StillVisible As Int
	Public TouchSlop As Int

	Private Window As Panel
	Private wParent As Panel
	Private wActionBar As ClsActionBar
	Private wTitleBar As Panel
	Private wContent As Panel
	Private wFrame As Panel
	Private wModule As Object

	Private btnPin As View
	Private btnMaximize As View
	Private btnClose As View
	Private btnResize As ImageView
	Private wResizeBtnSize As Int
	Private OnPinWinSub, OnMaximizeWinSub, OnCloseWinSub As String
	Private wPinDrawable, wMaximizeDrawable, wCloseDrawable, wResizeDrawable As Object
	Private wPinned, wMaximized As Boolean
	Private wSavedLayout As Rect
	Private wHideOnlyWhenClose As Boolean

	Private wStartX, wStartY As Int
	Private wMoveInProgress, wResizeMode As Boolean
	Private edtInputType, edtSelectionStart As Int
	Private OnMoveWinSub, OnResizeWinSub As String

	Private DockingAreas As List
	Private DockingPanel As Panel
	Private wDocked As Boolean
	Private OnEnterDockAreaWinSub, OnDockWinSub, OnUndockWinSub As String
	Private StickyAreas As Map
	Private StickyPanel(4) As Panel
	Private wStickyEdgeEnabled As Boolean
	Private OnStickWinSub As String
	Private Anim As Animation
	Private AfterAnim As typAfterAnim
	Type typAfterAnim(WinLeft As Int, WinTop As Int, IsDocking As Boolean, _
	                  SubName As String, DARect As Rect, SEdge As Int)
End Sub

'Initializes the floating window
'Parent = activity or panel holding the window
'Module = Me
Public Sub Initialize(Parent As Panel, Left As Int, Top As Int, Width As Int, Height As Int, Module As Object)
	wParent = Parent
	If Not(wParent.IsInitialized) Then
		Log("'Parent' must be the current activity or an initialized panel")
		Return
	End If
	Window.Initialize("")
	wParent.AddView(Window, Left, Top, Width, Height)

	wActionBar.Initialize(Window, True, True, 40dip, Me)
	wActionBar.Title.Left = 10dip
	wActionBar.Title.TextSize = 16
	wTitleBar = wActionBar.AsPanel
	wPinDrawable = wActionBar.LoadDrawable("ic_menu_goto")
	wMaximizeDrawable = wActionBar.LoadDrawable("btn_zoom_page_normal")
	wCloseDrawable = wActionBar.LoadDrawable("btn_close_normal")
	wResizeDrawable = wActionBar.LoadDrawable("ic_btn_square_browser_zoom_page_overview_normal")
	SetOnTouchListener(wTitleBar)

	wContent.Initialize("")
	wContent.Color = Colors.White
	Window.AddView(wContent, 0, wTitleBar.Height, -1, Height - wTitleBar.Height)
	SetOnTouchListener(wContent)

	wFrame.Initialize("")
	wFrame.Color = Colors.Transparent
	Window.AddView(wFrame, 0, 0, Width, Height)
	SetBorder(Colors.Black, 1dip)

	DockingAreas.Initialize
	StickyAreas.Initialize
	DockingAreaColor = Colors.ARGB(128, 128, 128, 128)
	StickyAreaColor = Colors.ARGB(128, 128, 128, 128)
	wDocked = False
	MinimumCoveredSurfaceForDocking = 0 'Not used by default
	wStickyEdgeEnabled = False

	Dim r As Reflector
	r.Target = r.RunStaticMethod("android.view.ViewConfiguration", "get", Array As Object(r.GetContext), Array As String("android.content.Context"))
	TouchSlop = r.RunMethod("getScaledTouchSlop")

	PinnedWindowMsg = "This window is pinned. It cannot be moved or resized."
	wMoveInProgress = False
	wResizeMode = False
	wResizeBtnSize = 30dip
	MinimumWidthAfterResize = 40dip
	MinimumHeightAfterResize = 40dip + wResizeBtnSize
	MaximumWidthAfterResize = wParent.Width
	MaximumHeightAfterResize = wParent.Height
	StillVisible = 100dip
	wModule = Module
End Sub

#Region Title bar
'Shows/Hides the title bar
Public Sub EnableTitleBar(Enabled As Boolean)
	If wTitleBar.Visible <> Enabled Then
		wTitleBar.Visible = Enabled
		If wTitleBar.Visible Then
			wContent.Top = wTitleBar.Height
		Else
			wContent.Top = 0
		End If
		wContent.Height = getHeight - wContent.Top
		If btnResize.IsInitialized Then btnResize.Top = wContent.Height - wResizeBtnSize
	End If
End Sub

'Changes the title background
'Background = a valid drawable
Public Sub SetTitleBackground(Background As Object)
	wActionBar.SetBackground(Background)
End Sub

'Changes the window title text
Public Sub SetTitleText(Text As String)
	wActionBar.Title.Text = Text
End Sub

'Changes the title text color
Public Sub SetTitleTextColor(Color As Int)
	wActionBar.Title.TextColor = Color
End Sub

'Changes the title text size
Public Sub SetTitleTextSize(Size As Int)
	wActionBar.Title.TextSize = Size
End Sub
#End Region

#Region Buttons
'Adds a custom button in the title bar
'Icon = a valid bitmap or drawable
'Position = position in the title bar, starting from the right (1 = rightmost position)
'OnClickSub = name of the sub to call in your module when the button is pressed
'OnLongClickSub = name of the sub to call in your module after a long click
'Returns a pointer on the new button
Public Sub AddCustomButton(Icon As Object, Position As Int, OnClickSub As String, OnLongClickSub As String) As View
	Dim MyBtn As View, Action As typAction
	MyBtn = wActionBar.AddButton(Icon, "", 5, -Position, "CustomButton_Click", "CustomButton_LongClick")
	Action = MyBtn.Tag
	Action.Tag = OnClickSub & "|" & OnLongClickSub
	SetOnTouchListener(MyBtn)
	Return MyBtn
End Sub

Private Sub CustomButton_Click(ActionBar As ClsActionBar, Btn As View)
	' Redirects the Click event
	Dim Action As typAction, ClickSub As String
	Action = Btn.Tag
	ClickSub = Action.Tag
	ClickSub = ClickSub.SubString2(0, ClickSub.IndexOf("|"))
	If SubExists(wModule, ClickSub) Then CallSub3(wModule, ClickSub, Me, Btn)
End Sub

Private Sub CustomButton_LongClick(ActionBar As ClsActionBar, Btn As View)
	' Redirects the LongClick event
	Dim Action As typAction, LongClickSub As String
	Action = Btn.Tag
	LongClickSub = Action.Tag
	LongClickSub = LongClickSub.SubString(LongClickSub.IndexOf("|") + 1)
	If SubExists(wModule, LongClickSub) Then CallSub3(wModule, LongClickSub, Me, Btn)
End Sub

Private Sub UpdateStateDrawables(Selected As Boolean, Btn As View)
	Dim sd As StateListDrawable
	sd.Initialize
	If Selected Then
		sd.AddState(sd.State_Pressed, wActionBar.LoadDrawable("list_selector_background_pressed"))
		sd.AddCatchAllState(wActionBar.LoadDrawable("list_selector_background_focus"))
	Else
		Btn.Color = Colors.Transparent
		sd.AddState(sd.State_Pressed, wActionBar.LoadDrawable("list_selector_background_pressed"))
		sd.AddState(sd.State_Selected, wActionBar.LoadDrawable("list_selector_background_focus"))
		sd.AddCatchAllState(Btn.Background)
	End If
	Btn.Background = sd
End Sub

'Shows/Hides the pin button in the title bar
'OnPinSub = name of the sub to call in your module after the window is pinned
Public Sub EnablePinButton(Enabled As Boolean, OnPinSub As String)
	If Enabled <> btnPin.IsInitialized Then
		If Enabled Then
			btnPin = wActionBar.AddButton(wPinDrawable, "", 5, -wActionBar.GetRightCount-1, "btnPin_Click", "")
			SetOnTouchListener(btnPin)
		Else
			wActionBar.RemoveButton(btnPin)
			btnPin = Null
		End If
	End If
	OnPinWinSub = OnPinSub
End Sub

'Changes the pin button icon
'Icon = a valid bitmap or drawable
Public Sub ChangePinIcon(NewIcon As Object)
	If NewIcon = Null Then Return
	If NewIcon Is Bitmap Then
		Dim bd As BitmapDrawable
		bd.Initialize(NewIcon)
		wPinDrawable = bd
	Else
		wPinDrawable = NewIcon
	End If
	If btnPin.IsInitialized Then wActionBar.ReplaceIcon(btnPin, wPinDrawable)
End Sub

Private Sub btnPin_Click(ActionBar As ClsActionBar, Btn As View)
	'Pins the window on its parent (cannot move)
	wPinned = Not(wPinned)

	'Update the state drawables
	UpdateStateDrawables(wPinned, Btn)
	If SubExists(wModule, OnPinWinSub) Then CallSub2(wModule, OnPinWinSub, Me)
End Sub

'Is the window pinned ?
Public Sub IsPinned As Boolean
	Return wPinned
End Sub

'Shows/Hides the maximize/restore button in the title bar
'OnMaximizeSub = name of the sub to call in your module after the window is maximized/restored
Public Sub EnableMaximizeButton(Enabled As Boolean, OnMaximizeSub As String)
	If Enabled <> btnMaximize.IsInitialized Then
		If Enabled Then
			btnMaximize = wActionBar.AddButton(wMaximizeDrawable, "", 5, -wActionBar.GetRightCount-1, "btnMaximize_Click", "")
			SetOnTouchListener(btnMaximize)
		Else
			wActionBar.RemoveButton(btnMaximize)
			btnMaximize = Null
		End If
	End If
	OnMaximizeWinSub = OnMaximizeSub
End Sub

'Changes the maximize button icon
'Icon = a valid bitmap or drawable
Public Sub ChangeMaximizeIcon(NewIcon As Object)
	If NewIcon = Null Then Return
	If NewIcon Is Bitmap Then
		Dim bd As BitmapDrawable
		bd.Initialize(NewIcon)
		wMaximizeDrawable = bd
	Else
		wMaximizeDrawable = NewIcon
	End If
	If btnMaximize.IsInitialized Then wActionBar.ReplaceIcon(btnMaximize, wMaximizeDrawable)
End Sub

'Enlarges the window to fill its parent (MaxSize=True) or returns to its previous position and size (MaxSize=False)
Public Sub Maximize(MaxSize As Boolean)
	If wPinned Then
		ToastMessageShow(PinnedWindowMsg, False)
		Return
	End If
	If MaxSize AND Not(wMaximized) Then
		wSavedLayout.Initialize(Window.Left, Window.Top, getWidth, getHeight)
		MoveWin(0, 0, False)
		ResizeWin(wParent.Width, wParent.Height, 0, 0, wParent.Width, wParent.Height)
		BringOnTop
		wMaximized = True
		If btnMaximize.IsInitialized Then UpdateStateDrawables(wMaximized, btnMaximize)
		If SubExists(wModule, OnMaximizeWinSub) Then CallSub2(wModule, OnMaximizeWinSub, Me)
	Else If Not(MaxSize) AND wMaximized Then
		Resize(wSavedLayout.Right, wSavedLayout.Bottom)
		MoveWin(wSavedLayout.Left, wSavedLayout.Top, True)
		wSavedLayout = Null
		wMaximized = False
		If btnMaximize.IsInitialized Then UpdateStateDrawables(wMaximized, btnMaximize)
		If SubExists(wModule, OnMaximizeWinSub) Then CallSub2(wModule, OnMaximizeWinSub, Me)
	End If
End Sub

Private Sub btnMaximize_Click(ActionBar As ClsActionBar, Btn As View)
	Maximize(Not(wMaximized))
End Sub

'Is the window maximized ?
Public Sub IsMaximized As Boolean
	Return wMaximized
End Sub

'Shows/Hides the close button in the title bar
'HideOnly = if True, closing the window just hides it
'OnCloseSub = name of the sub to call in your module before the window is closed
Public Sub EnableCloseButton(Enabled As Boolean, HideOnly As Boolean, OnCloseSub As String)
	If Enabled <> btnClose.IsInitialized Then
		If Enabled Then
			btnClose = wActionBar.AddButton(wCloseDrawable, "", 5, -1, "btnClose_Click", "")
			SetOnTouchListener(btnClose)
		Else
			wActionBar.RemoveButton(btnClose)
			btnClose = Null
		End If
	End If
	wHideOnlyWhenClose = HideOnly
	OnCloseWinSub = OnCloseSub
End Sub

'Changes the close button icon
'Icon = a valid bitmap or drawable
Public Sub ChangeCloseIcon(NewIcon As Object)
	If NewIcon = Null Then Return
	If NewIcon Is Bitmap Then
		Dim bd As BitmapDrawable
		bd.Initialize(NewIcon)
		wCloseDrawable = bd
	Else
		wCloseDrawable = NewIcon
	End If
	If btnClose.IsInitialized Then wActionBar.ReplaceIcon(btnClose, wCloseDrawable)
End Sub

Private Sub btnClose_Click(ActionBar As ClsActionBar, Btn As View)
	If SubExists(wModule, OnCloseWinSub) Then CallSub2(wModule, OnCloseWinSub, Me)
	If wHideOnlyWhenClose Then
		Hide
	Else
		Close
	End If
End Sub

'Shows/Hides the resize button in the bottom right corner
Public Sub EnableResizeButton(Enabled As Boolean)
	If Enabled <> btnResize.IsInitialized Then
		If Enabled Then
			btnResize.Initialize("")
			btnResize.Background = wResizeDrawable
			btnResize.Gravity = Gravity.FILL
			wContent.AddView(btnResize, getWidth - wResizeBtnSize, getContentHeight - wResizeBtnSize, wResizeBtnSize, wResizeBtnSize)
			SetOnTouchListener(btnResize)
		Else
			btnResize.RemoveView
			btnResize = Null
		End If
	End If
End Sub

'Changes the resize button icon
'Icon = a valid bitmap or drawable
Public Sub ChangeResizeIcon(NewIcon As Object)
	If NewIcon = Null Then Return
	If NewIcon Is Bitmap Then
		Dim bd As BitmapDrawable
		bd.Initialize(NewIcon)
		wResizeDrawable = bd
	Else
		wResizeDrawable = NewIcon
	End If
	btnResize.Background = wResizeDrawable
End Sub
#End Region

'Draws a colored frame around the window
Public Sub SetBorder(Color As Int, Width As Int)
	Dim C As Canvas, wRect As Rect
	C.Initialize(wFrame)
	C.DrawColor(Colors.Transparent)
	wRect.Initialize(0 + (Width/2), 0 + (Width/2), getWidth - (Width/2), getHeight - (Width/2))
	C.DrawRect(wRect, Color, False, Width)
End Sub

'Changes the main content background
'Background = a valid drawable
Public Sub SetBackground(Background As Object)
	wContent.Background = Background
End Sub

'Adds a view to the window
'DelegateTouchEvent: if True, the Touch event is handled by the class and allows to move the window.
'Some views like ListView or ScrollView need DelegateTouchEvent=False if their content is not fully displayed (that allows to scroll their content but prevents from moving the window by moving the view).
Public Sub AddView(MyView As View, Left As Int, Top As Int, Width As Int, Height As Int, DelegateTouchEvent As Boolean)
	wContent.AddView(MyView, Left, Top, Width, Height)
	If DelegateTouchEvent Then SetOnTouchListener(MyView)
	If btnResize.IsInitialized Then btnResize.BringToFront
End Sub

#Region Left, Top, Width, Height
'Gets the window left value
Public Sub getLeft As Int
	Return Window.Left
End Sub

'Gets the window top value
Public Sub getTop As Int
	Return Window.Top
End Sub

'Gets the window width
Public Sub getWidth As Int
	If Window.Width < 0 Then
		Dim r As Reflector, Largeur As Int
		r.Target = Window
		Largeur = r.RunMethod("getWidth")
		If Largeur = 0 Then
			DoEvents
			Largeur = r.RunMethod("getWidth")
		End If
		Return Largeur		
	Else
		Return Window.Width
	End If
End Sub

'Gets the window height
'If you want only the height of the content panel, call getContentHeight
Public Sub getHeight As Int
	If Window.Height < 0 Then
		Dim r As Reflector, Hauteur As Int
		r.Target = Window
		Hauteur = r.RunMethod("getHeight")
		If Hauteur = 0 Then
			DoEvents
			Hauteur = r.RunMethod("getHeight")
		End If
		Return Hauteur		
	Else
		Return Window.Height
	End If
End Sub

'Gets the content panel height
'ContentHeight = WindowHeight - ActionBarHeight
Public Sub getContentHeight As Int
	Return getHeight - wTitleBar.Height
End Sub
#End Region

'Brings the window to the front
Public Sub BringOnTop()
	' Successive calls to BringToFront create an issue with focus,
	' so we only call BringToFront when needed
	Dim OnTop As Boolean
	If wParent Is Activity Then
		Dim act As Activity
		act = wParent
		OnTop = (act.GetView(act.NumberOfViews - 1) = Window)
	Else
		Dim pnl As Panel
		pnl = wParent
		OnTop = (pnl.GetView(pnl.NumberOfViews - 1) = Window)
	End If
	If Not(OnTop) Then Window.BringToFront
End Sub

Private Sub SetOnTouchListener(MyView As View)
	Dim r As Reflector
	r.Target = MyView
	r.SetOnTouchListener("Content_Touch")
End Sub

Private Sub AllowInputInEditText(MyET As Object, Enabled As Object)
	Dim edt As EditText: edt = MyET
	If Enabled = True Then
		edt.InputType = edtInputType
		edt.SelectionStart = edtSelectionStart
	Else
		edtInputType = edt.InputType
		edtSelectionStart = edt.SelectionStart
		edt.InputType = 0
		edt.SelectionStart = edtSelectionStart
	End If
End Sub

Private Sub Content_Touch(ViewTag As Object, Action As Int, X As Float, Y As Float, MotionEvent As Object) As Boolean
	Dim SenderIsWindow As Boolean
	SenderIsWindow = (Sender = Window OR Sender = wTitleBar OR _
	                  Sender = wContent OR Sender = wFrame)
	Select Action
		Case 0 ' DOWN
			' We bring the window to the front
			BringOnTop

			' We undock the window
			If wDocked Then
				wDocked = False
				If SubExists(wModule, OnUndockWinSub) Then
					Dim OldX, OldY As Int
					OldX = getLeft
					OldY = getTop
					CallSub2(wModule, OnUndockWinSub, Me)
					' We adjust the touch coordinates if the window has been moved in OnUndockWinSub
					X = X + OldX - getLeft
					Y = Y + OldY - getTop
				End If
			End If
			CheckSpecialAreas(False)

			' We memorize the starting position
			wStartX = X
			wStartY = Y
			wMoveInProgress = False

			' We turn the resize mode on if the user pressed the resize button
			If btnResize.IsInitialized Then
				If Sender = btnResize Then
					If wPinned Then
						ToastMessageShow(PinnedWindowMsg, False)
					Else
						wResizeMode = True
					End If
				End If
			End If

		Case 1 ' UP
			' We perform all actions related to the docking and sticky areas
			CheckSpecialAreas(True)
			If wMoveInProgress Then
				wMoveInProgress = False
				If Sender Is ListView Then Return True
				If Sender Is EditText Then AllowInputInEditText(Sender, True)
			End If
			wResizeMode = False

		Case 2 ' MOVE
			If Not(wMaximized OR wPinned) Then ' We don't move/resize a maximized or pinned window
				' We block the interception of touch events
				Dim r As Reflector
				r.Target = Sender
				If Sender Is ListView OR Sender Is ScrollView Then
					r.RunMethod2("requestDisallowInterceptTouchEvent", True, "java.lang.boolean")
				End If

				' Is the move big enough to be considered as a move ?
				Dim MoveQty As Int
				MoveQty = Sqrt(Power(Abs(X - wStartX), 2) + Power(Abs(Y - wStartY), 2))
				If wMoveInProgress OR MoveQty > TouchSlop Then
					' We move/resize the window
					If wResizeMode Then
						Resize(Window.Width + X - wStartX, Window.Height + Y - wStartY)
						wStartX = X
						wStartY = Y
					Else
						MoveWin(Window.Left + X - wStartX, Window.Top + Y - wStartY, True)
					End If
					CheckSpecialAreas(False)
					If Not(SenderIsWindow) Then
						' We cancel the pressed and selected states
		   			r.RunMethod2("setPressed", "False", "java.lang.boolean")
		   			r.RunMethod2("setSelected", "False", "java.lang.boolean")
					End If
					If Not(wMoveInProgress) Then
						wMoveInProgress = True
						If r.Target Is EditText Then
					 		' No input is allowed in an EditText while moving
							' This also prevents the soft keyboard from appearing
							AllowInputInEditText(r.Target, False)
						End If
					End If
				End If

			End If
	End Select
	Return SenderIsWindow
End Sub

#Region Move & Resize
Private Sub ResizeWin(NewWidth As Int, NewHeight As Int, MinWidth As Int, MinHeight As Int, _
                                                         MaxWidth As Int, MaxHeight As Int)
	If NewWidth <> -1 Then
		NewWidth = Min(Max(NewWidth, MinWidth), MaxWidth)
		Window.Width = NewWidth
		wTitleBar.Width = NewWidth
		wActionBar.Invalidate
		wContent.Width = NewWidth
		wFrame.Width = NewWidth
		If btnResize.IsInitialized Then btnResize.Left = NewWidth - wResizeBtnSize
	End If
	If NewHeight <> -1 Then
		NewHeight = Min(Max(NewHeight, MinHeight), MaxHeight)
		Window.Height = NewHeight
		If wTitleBar.Visible Then
			wContent.Height = NewHeight - wTitleBar.Height
		Else
			wContent.Height = NewHeight
		End If
		wFrame.Height = NewHeight
		If btnResize.IsInitialized Then btnResize.Top = wContent.Height - wResizeBtnSize
	End If
	If SubExists(wModule, OnResizeWinSub) Then CallSub2(wModule, OnResizeWinSub, Me)
End Sub

'Resizes the window
'If a dimension is set to -1, it is left unchanged.
Public Sub Resize(NewWidth As Int, NewHeight As Int)
	If wPinned Then
		Log(PinnedWindowMsg)
		Return
	End If
	ResizeWin(NewWidth, NewHeight, MinimumWidthAfterResize, MinimumHeightAfterResize, _
	                               MaximumWidthAfterResize, MaximumHeightAfterResize)
End Sub

'Adds a listener for events onResize (fired after a resize)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow)
Public Sub SetOnResizeListener(SubName As String)
	OnResizeWinSub = SubName
End Sub

Private Sub CalcNewLeft(NewLeft As Int) As Int
	Return Max(StillVisible - getWidth, Min(NewLeft, wParent.Width - StillVisible))
End Sub
Private Sub CalcNewTop(NewTop As Int) As Int
	Return Max(StillVisible - getHeight, Min(NewTop, wParent.Height - StillVisible))
End Sub
Private Sub MoveWin(NewLeft As Int, NewTop As Int, CheckStillVisible As Boolean)
	If CheckStillVisible Then
		If NewLeft <> -1 Then
			Window.Left = CalcNewLeft(NewLeft)
		End If
		If NewTop <> -1 Then
			Window.Top = CalcNewTop(NewTop)
		End If
	Else
		If NewLeft <> -1 Then Window.Left = NewLeft
		If NewTop <> -1 Then Window.Top = NewTop
	End If
	If SubExists(wModule, OnMoveWinSub) Then CallSub2(wModule, OnMoveWinSub, Me)
End Sub

'Moves the window
'If a position is set to -1, it is left unchanged.
'IgnoreSpecialAreas = if True, docking areas and sticky edges are ignored.
Public Sub Move(NewLeft As Int, NewTop As Int, IgnoreSpecialAreas As Boolean)
	If wPinned Then
		Log(PinnedWindowMsg)
		Return
	End If
	If NewLeft <> getLeft AND NewLeft <> -1 AND NewTop <> getTop AND NewTop <> -1 Then
		' The window leaves the docking area
		wDocked = False
	End If
	MoveWin(NewLeft, NewTop, True)
	If Not(IgnoreSpecialAreas) Then CheckSpecialAreas(True)
End Sub

'Adds a listener for events onMove (fired after a move)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow)
Public Sub SetOnMoveListener(SubName As String)
	OnMoveWinSub = SubName
End Sub
#End Region

'Shows a hidden window
Public Sub Show
	Window.Visible = True
End Sub

'Hides a window
Public Sub Hide
	Window.Visible = False
End Sub

'Gets the window panel
Public Sub AsPanel As Panel
	Return Window
End Sub

'Clears the content and closes the window
Public Sub Close
	Dim v As View
	For i = wContent.NumberOfViews - 1 To 0 Step -1
		v = wContent.GetView(i)
		v.RemoveView
	Next
	For i = Window.NumberOfViews - 1 To 0 Step -1
		v = Window.GetView(i)
		v.RemoveView
	Next
	Window.RemoveView
End Sub

#Region Dock & Stick
Private Sub UpdateAfterAnimPosition(Left As Int, Top As Int)
	If Anim.IsInitialized Then
		If AfterAnim.WinLeft = -1 AND Left <> -1 Then AfterAnim.WinLeft = Left
		If AfterAnim.WinTop = -1 AND Top <> -1 Then AfterAnim.WinTop = Top
	Else
		AfterAnim.WinLeft = Left
		AfterAnim.WinTop = Top
	End If
End Sub

Private Sub CalcSurface(rectDock As Rect) As Long
	'Computes the covered area
	Dim SurfaceW As Int
	Dim WinRight As Int = Window.Left + Window.Width
	If Window.Left >= rectDock.Left Then
		If WinRight <= rectDock.Right Then
			SurfaceW = Window.Width
		Else
			SurfaceW = rectDock.Right - Window.Left
		End If
	Else
		If WinRight >= rectDock.Right Then
			SurfaceW = rectDock.Right - rectDock.Left
		Else
			SurfaceW = WinRight - rectDock.Left
		End If
	End If

	Dim SurfaceH As Int
	Dim WinBottom As Int = Window.Top + Window.Height
	If Window.Top >= rectDock.Top Then
		If WinBottom <= rectDock.Bottom Then
			SurfaceH = Window.Height
		Else
			SurfaceH = rectDock.Bottom - Window.Top
		End If
	Else
		If WinBottom >= rectDock.Bottom Then
			SurfaceH = rectDock.Bottom - rectDock.Top
		Else
			SurfaceH = WinBottom - rectDock.Top
		End If
	End If

	Return SurfaceW * SurfaceH
End Sub

Private Sub CheckSpecialAreas(PerformAction As Boolean)
	' Initialisations
	AfterAnim.Initialize
	AfterAnim.WinLeft = -1
	AfterAnim.WinTop = -1

	' Docking areas
	Dim wRect As Rect
	If DockingPanel.IsInitialized Then
		DockingPanel.Visible = False
		If Not(wMaximized) Then
			Dim Surface, BiggestSurface As Long, SelectedArea As Int
			SelectedArea = -1
			For i = 0 To DockingAreas.Size - 1
				wRect = DockingAreas.Get(i)
				If (Window.Left <= wRect.Right And Window.Left + getWidth >= wRect.Left) And _
		   		(Window.Top <= wRect.Bottom And Window.Top + getHeight >= wRect.Top) Then
					' The window is in a docking area
					' We calculate the covered area
					Surface = CalcSurface(wRect)
					If Surface > BiggestSurface Then
						' We select the docking area with the most covered surface
						SelectedArea = i
						BiggestSurface = Surface
					End If
				End If
			Next
			If SelectedArea <> -1 Then
				wRect = DockingAreas.Get(SelectedArea)
				Dim ActionIsConfirmed As Boolean
				If PerformAction AND MinimumCoveredSurfaceForDocking > 0 Then
					Dim CoveredSurface As Float
					CoveredSurface = (BiggestSurface / ((wRect.Right - wRect.Left) * (wRect.Bottom - wRect.Top))) * 100
					ActionIsConfirmed = (CoveredSurface >= MinimumCoveredSurfaceForDocking)
				Else
					ActionIsConfirmed = True
				End If
				If PerformAction AND ActionIsConfirmed Then
					UpdateAfterAnimPosition(wRect.Left, wRect.Top)
					Anim.InitializeTranslate("Anim", 0, 0, wRect.Left - Window.Left, wRect.Top - Window.Top)
					Anim.Duration = 100
					AfterAnim.SubName = OnDockWinSub
					AfterAnim.IsDocking = True
					AfterAnim.DARect = wRect
					If wStickyEdgeEnabled Then HideStickyPanels
					Anim.Start(Window)
					Return ' We bypass the sticky edge check
				Else
					DockingPanel.SetLayout(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top)
					DockingPanel.Color = DockingAreaColor
					DockingPanel.Visible = (DockingAreaColor <> Colors.Transparent)
					If SubExists(wModule, OnEnterDockAreaWinSub) Then CallSub3(wModule, OnEnterDockAreaWinSub, Me, wRect)
				End If
			End If
		End If
	End If

	' Sticky areas
	If wStickyEdgeEnabled Then
		HideStickyPanels
		If Not(wMaximized) Then
			Dim Edge As Int
			For i = 0 To StickyAreas.Size - 1
				Edge = StickyAreas.GetKeyAt(i)
				Select Edge
					Case 0 'LEFT
						wRect.Initialize(0, 0, StickyAreas.GetValueAt(i), wParent.Height)
					Case 1 'TOP
						wRect.Initialize(0, 0, wParent.Width, StickyAreas.GetValueAt(i))
					Case 2 'RIGHT
						wRect.Initialize(wParent.Width - StickyAreas.GetValueAt(i), 0, wParent.Width, wParent.Height)
					Case 3 'BOTTOM
						wRect.Initialize(0, wParent.Height - StickyAreas.GetValueAt(i), wParent.Width, wParent.Height)
				End Select
				If (Window.Left <= wRect.Right AND Window.Left + getWidth >= wRect.Left) AND _
				   (Window.Top <= wRect.Bottom AND Window.Top + getHeight >= wRect.Top) Then
					' The window is in the sticky area
					If PerformAction Then
						Select Edge
							Case 0 'LEFT
								UpdateAfterAnimPosition(CalcNewLeft(0), -1)
							Case 1 'TOP
								UpdateAfterAnimPosition(-1, CalcNewTop(0))
							Case 2 'RIGHT
								UpdateAfterAnimPosition(CalcNewLeft(wParent.Width - getWidth), -1)
							Case 3 'BOTTOM
								UpdateAfterAnimPosition(-1, CalcNewTop(wParent.Height - getHeight))
						End Select
						Dim DestX, DestY As Int
						If AfterAnim.WinLeft <> -1 Then DestX = AfterAnim.WinLeft - Window.Left
						If AfterAnim.WinTop <> -1 Then DestY = AfterAnim.WinTop - Window.Top
						If DestX <> 0 OR DestY <> 0 Then
							Anim.InitializeTranslate("Anim", 0, 0, DestX, DestY)
							Anim.Duration = 200
							AfterAnim.SubName = OnStickWinSub
							AfterAnim.IsDocking = False
							AfterAnim.SEdge = Edge
							Anim.Start(Window)
						End If
					Else If Not(IsDocked OR (Anim.IsInitialized AND AfterAnim.IsDocking)) Then
						StickyPanel(Edge).SetLayout(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top)
						StickyPanel(Edge).Color = StickyAreaColor
						StickyPanel(Edge).Visible = (StickyAreaColor <> Colors.Transparent)
					End If
				End If
			Next
		End If
	End If
End Sub

Private Sub Anim_AnimationEnd
	'Sets the final position and destroys the animation
	If AfterAnim.IsDocking Then
		wDocked = True
		MoveWin(AfterAnim.WinLeft, AfterAnim.WinTop, False)
		ResizeWin(AfterAnim.DARect.Right - AfterAnim.DARect.Left, AfterAnim.DARect.Bottom - AfterAnim.DARect.Top, 0, 0, _
		          AfterAnim.DARect.Right - AfterAnim.DARect.Left, AfterAnim.DARect.Bottom - AfterAnim.DARect.Top)
		If SubExists(wModule, AfterAnim.SubName) Then CallSub3(wModule, AfterAnim.SubName, Me, AfterAnim.DARect)
	Else
		MoveWin(AfterAnim.WinLeft, AfterAnim.WinTop, True)
		If SubExists(wModule, AfterAnim.SubName) Then CallSub3(wModule, AfterAnim.SubName, Me, AfterAnim.SEdge)
	End If
	Anim = Null
End Sub

'添加停靠区域
'“如果窗口进入停靠区域,则该区域将可见。
''如果移动结束时窗口仍在该区域中,则会移动窗口并调整其大小以适应该区域。
'Adds a docking area
'If a window enters a docking area, the area becomes visible.
'If the window is still in the area when the move ends, it is moved and resized to fit the area.
Public Sub AddDockingArea(DockRect As Rect)
	If Not(DockingPanel.IsInitialized) Then
		DockingPanel.Initialize("")
		wParent.AddView(DockingPanel, 0, 0, 0, 0)
		DockingPanel.Visible = False
	End If
	DockingAreas.Add(DockRect)
End Sub

'Removes all docking areas
Public Sub RemoveDockingAreas
	If DockingPanel.IsInitialized Then
		DockingPanel.RemoveView
		DockingPanel = Null
	End If
	DockingAreas.Clear
End Sub

'Adds a listener for the events OnEnterDockArea (fired when entering a docking area)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow, DockRect As Rect)
Public Sub SetOnEnterDockAreaListener(SubName As String)
	OnEnterDockAreaWinSub = SubName
End Sub

'Adds a listener for the events OnDock (fired after docking)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow, DockRect As Rect)
Public Sub SetOnDockListener(SubName As String)
	OnDockWinSub = SubName
End Sub

'Adds a listener for the events OnUndock (fired after leaving a docking area)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow)
Public Sub SetOnUndockListener(SubName As String)
	OnUndockWinSub = SubName
End Sub

'Is the window docked ?
Public Sub IsDocked As Boolean
	Return wDocked
End Sub

'Creates a sticky area near an edge.
'If the window enters the sticky area, the area becomes visible.
'If the window is still in the area when the move ends, it is sticked against the edge.
'Edge:
'0 = Left
'1 = Top
'2 = Right
'3 = Bottom
Public Sub AddStickyEdge(Edge As Int, Size As Int)
	If Edge < 0 OR Edge > 3 Then
		Log("Invalid Edge value. Must be 0, 1, 2 or 3.")
		Return
	End If
	StickyAreas.Put(Edge, Size)
	If Not(StickyPanel(Edge).IsInitialized) Then
		StickyPanel(Edge).Initialize("")
		wParent.AddView(StickyPanel(Edge), 0, 0, 0, 0)
		StickyPanel(Edge).Visible = False
		wStickyEdgeEnabled = True
	End If
End Sub

' Hides all sticky panels
Private Sub HideStickyPanels
	For i = 0 To 3
		If StickyPanel(i).IsInitialized Then StickyPanel(i).Visible = False
	Next
End Sub

'Removes all sticky areas
Public Sub RemoveStickyEdges
	For i = 0 To 3
		If StickyPanel(i).IsInitialized Then
			StickyPanel(i).RemoveView
			StickyPanel(i) = Null
		End If
	Next
	StickyAreas.Clear
	wStickyEdgeEnabled = False
End Sub

'Adds a listener for events OnStick (fired after sticking to an edge)
'Your listener must be declared like this: myListener(Window As ClsFloatingWindow, Edge As Int)
'Edge:
'0 = Left
'1 = Top
'2 = Right
'3 = Bottom
Public Sub SetOnStickListener(SubName As String)
	OnStickWinSub = SubName
End Sub
#End Region

#Region Tag
'Gets the tag value
Public Sub getTag As Object
	Return Window.Tag
End Sub

'Sets the tag value
Public Sub SetTag(NewValue As Object)
	Window.Tag = NewValue
End Sub
#End Region

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值