我想创建一个自定义视图,它应该水平滚动,它可以用作标题工具栏(作为操作栏)和页脚工具栏。
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
try
{
DisplayMetrics met = new DisplayMetrics();
display.GetMetrics(met);
m_fToolSize = (met.Xdpi * c_fToolIconSize) / c_fmmPerInch;
SetMeasuredDimension(met.WidthPixels, (int)(m_fToolSize + 2 * c_nToolIndent));
}
catch { }
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
try
{
int[] loc = new int[2];
GetLocationOnScreen(loc);
loc[1] -= SysUtil.GetStatusBarHeight(Resources);
Display dsp = ((Activity)Context).WindowManager.DefaultDisplay;
if (loc[1] < dsp.Height / 2)
{
m_bIsUpperToolBar = true;
}
int nToolSize = (int)m_fToolSize;
int nNumTools = (int)(((r - l) - (2 * c_nToolIndent)) / m_fToolSize);
m_fToolSpace = ((r - l) - 2 * c_nToolIndent - nNumTools * nToolSize) / (nNumTools - 1);
float x = c_nToolIndent, y = c_nToolIndent;
for (int i = 0; i < ChildCount; i++)// Removed condition of nNumTools to allow scrolling
{
GetChildAt(i).Layout((int)x, (int)y, (int)x + nToolSize, (int)y + nToolSize);
x += m_fToolSize + m_fToolSpace;
}
}
catch (Exception ex)
{
}
}
//To Implement Scrolling
//This allows a ViewGroup to watch events as they are dispatched to child Views
public override bool OnInterceptTouchEvent(MotionEvent e)
{
Console.WriteLine("OnInterceptTouchEvent");
Boolean intercept = false;
try
{
switch (e.Action)
{
case MotionEventActions.Move:
{
int xDiff = (int)Math.Abs(e.GetX() - m_fLastX);
if (xDiff > mTouchSlop)
{
m_nTouchState = c_nTouchStateHorizontalScrolling;
m_fLastX = e.GetX();
}
int yDiff = (int)Math.Abs(e.GetY() - m_fLastY);
if (yDiff > mTouchSlop)
{
m_nTouchState = -1;
}
if (Math.Abs(xDiff * 2) > Math.Abs(yDiff) && xDiff > mTouchSlop)
{
intercept = true;
}
break;
}
case MotionEventActions.Cancel:
case MotionEventActions.Up:
// Release the drag.
m_nTouchState = c_nTouchStateRest;
break;
case MotionEventActions.Down:
m_fLastY = e.GetY();
m_fLastX = e.GetX();
break;
default:
break;
}
}
catch (Exception ex)
{
}
return intercept;
}
public override bool OnTouchEvent(MotionEvent e)
{
Console.WriteLine("TB OnTouchEvent");
try
{
if (mVelocityTracker == null)
{
mVelocityTracker = VelocityTracker.Obtain();
}
mVelocityTracker.AddMovement(e);
float x = e.GetX();
float y = e.GetY();
switch (e.Action)
{
case MotionEventActions.Down:
if (!m_scroller.IsFinished)
{
m_scroller.AbortAnimation();
}
m_fLastX = x;
if (m_scroller.IsFinished)
{
m_nTouchState = c_nTouchStateRest;
}
else
{
m_nTouchState = c_nTouchStateHorizontalScrolling;
}
break;
case MotionEventActions.Move:
int deltaX = (int)(m_fLastX - x);
m_fLastX = x;
int scrollX = ScrollX;
// Scroll to right
if (deltaX < 0)
{
if (scrollX > 0)
{
ScrollBy(Math.Max(-scrollX, deltaX), 0);
}
}
// Scroll to left
else if (deltaX > 0)
{
// Visible full icons always without empty spaces
int availableToScroll =
GetChildAt(ChildCount - 1).Right - scrollX - (display.Width - c_nToolIndent);
if (availableToScroll > 0)
{
ScrollBy(Math.Min(availableToScroll, deltaX), 0);
}
}
break;
case MotionEventActions.Up:
//for (int index = 0; index < ChildCount; index++)
//{
// View v = GetChildAt(index);
// Rect rect = new Rect(v.Left, v.Top, v.Right, v.Bottom);
// if (v.GetLocalVisibleRect(rect))
// {
// // we are here because we are either clipped or fully visible
// int[] loc = new int[2];
// v.GetLocationOnScreen(loc);
// int n = v.Width;
// if (loc[0] < c_nToolIndent)
// {
// // identify clipped view
// if (Math.Abs(loc[0]) >= v.Width / 2)
// {
// // scroll the view outside the screen
// ScrollBy(v.Width + loc[0] + (int)m_fToolSpace - c_nToolIndent, 0);
// break;
// }
// else
// {
// ScrollBy(loc[0] - c_nToolIndent, 0);
// break;
// }
// }
// }
//}
VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.ComputeCurrentVelocity(1000, mMaximumVelocity);
int initialXVelocity = (int)velocityTracker.XVelocity;
int initialYVelocity = (int)velocityTracker.YVelocity;
if ((System.Math.Abs(initialXVelocity) + System.Math.Abs(initialYVelocity) > mMinimumVelocity) && ChildCount > 0)
{
Fling(-initialXVelocity, 0);
}
if (mVelocityTracker != null)
{
mVelocityTracker.Recycle();
mVelocityTracker = null;
}
break;
m_nTouchState = c_nTouchStateRest;
break;
case MotionEventActions.Cancel:
m_nTouchState = c_nTouchStateRest;
break;
default:
break;
}
}
catch (Exception ex)
{
}
return true;
}
public void Fling(int velocityX, int velocityY)
{
Console.WriteLine("TB Fling");
if (ChildCount > 0)
{
int height = Height - PaddingBottom - PaddingTop;
int bottom = GetChildAt(0).Height;
int width = Width - PaddingRight - PaddingLeft;
int right = GetChildAt(0).Width;
m_scroller.Fling(ScrollX, 0, velocityX, 0, 0, 1300, 0, 0);
bool movingDown = velocityY > 0;
bool movingRight = velocityX > 0;
// View newFocused = findFocusableViewInMyBounds(movingRight, mScroller.FinalX, movingDown, mScroller.FinalY, FindFocus());
AwakenScrollBars(m_scroller.Duration);
Invalidate();
}
}