我想知道 ListView 中 ViewCell 的滚动位置。
尝试了各种方法,但总是给我 0 值。
我的意图是获取 ViewCell 在屏幕中的位置。为了解决这个问题,试图获取它的滚动位置,然后我会将此值添加到 ListView 对象的 Y 值中。
在这种情况下,有人可以帮助我吗?
我想知道 ListView 中 ViewCell 的滚动位置。
尝试了各种方法,但总是给我 0 值。
我的意图是获取 ViewCell 在屏幕中的位置。为了解决这个问题,试图获取它的滚动位置,然后我会将此值添加到 ListView 对象的 Y 值中。
在这种情况下,有人可以帮助我吗?
我找到了解决方案,
问题 :
我的意图是获取 ViewCell 在屏幕中的位置
解决方案 :
- 第 1 步:将滚动视图保持在相对布局内。
- 第二步:当用户点击滚动视图的 ViewCell 时,保存相关布局的触摸点(X,Y)。在 Y 坐标中,添加相对布局的顶部位置,这样您将获得相对于整个屏幕的触摸点。
- 第 3 步:当用户点击滚动视图的 ViewCell 时,调用 XYZ() 方法。
- 第 4 步:在 XYZ() 方法中,执行 (X, Y) 坐标所需的任何功能。(注意:在 XYZ() 方法中执行功能延迟 300 毫秒,因为步骤 2 需要一些时间来保存接触点。)
您必须使 ViewCell 的自定义渲染器将位置发送到 pcl 有点棘手,然后我们在视图中订阅事件这是我的代码
PCL
public class SAChatViewCell : ViewCell
{
public delegate int[] IntEventHandler(object sender, float[] postion);
public event IntEventHandler OnCellItemLongClicked;
public event EventHandler OnCellItemTouched;
public void InvokeOnCellItemLongClicked(object sender, float[] e)
{
//send the current grid
OnCellItemLongClicked?.Invoke(sender, e);
}
public void InvokeOnCellItemTouched(object sender, EventArgs e)
{
//send the current grid
OnCellItemTouched?.Invoke(sender, e);
}
}
安卓渲染器
class SAChatViewCellRenderer : ViewCellRenderer
{
private bool selected;
ClickListener handler = new ClickListener();
static Android.Widget.ListView listView;
Xamarin.Forms.ListView listviewforms;
static SAChatViewCell cellElement;
Android.Views.View cellControl;
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
{
try
{
if (cellControl == null)
{
cellControl = base.GetCellCore(item, convertView, parent, context);
}
cellElement = item as SAChatViewCell;
selected = false;
listviewforms = cellElement.View.Parent.Parent as Xamarin.Forms.ListView;
if (listviewforms == null)
{
return null;
}
if (listviewforms.BackgroundColor.ToAndroid() == Color.Transparent.ToAndroid())
{
cellControl.SetBackgroundColor(Color.White.ToAndroid());
}
else
{
cellControl.SetBackgroundColor(listviewforms.BackgroundColor.ToAndroid());
}
cellControl.SetOnLongClickListener(handler);
cellControl.SetOnTouchListener(handler);
return cellControl;
}
catch (Exception ex)
{
return null;
}
}
protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
{
base.OnCellPropertyChanged(sender, args);
if (args.PropertyName == "IsSelected")
{
// I had to create a property to track the selection because cellCore.Selected is always false.
// Toggle selection
selected = !selected;
var selectedBackground = cellElement.SelectedBackgroundColor.ToAndroid();
if (selected)
{
if (selectedBackground == Color.Transparent.ToAndroid())
{
cellControl.SetBackgroundColor(Color.White.ToAndroid());
return;
}
cellControl.SetBackgroundColor(selectedBackground);
}
else
{
if (listviewforms.BackgroundColor.ToAndroid() == Color.Transparent.ToAndroid())
{
cellControl.SetBackgroundColor(Color.White.ToAndroid());
}
else
{
cellControl.SetBackgroundColor(listviewforms.BackgroundColor.ToAndroid());
}
}
}
}
internal class ClickListener : Java.Lang.Object, IOnLongClickListener, IOnTouchListener
{
//event priority Touch - LongClick - Click
//NOTE: return true to indicate that we have handled the event and it should stop here;
public bool OnLongClick(Android.Views.View sender)
{
var cellItem = sender as INativeElementView;
var viewCell = sender as Android.Views.View;
float[] location = new float[] { 0, 0 };
Android.Views.View parentRow = (Android.Views.View)viewCell.Parent;
listView = (Android.Widget.ListView)parentRow.Parent;
int position = listView.GetPositionForView(parentRow);
var x = parentRow.Right;
var y = (parentRow.Top - listView.DividerHeight) <= 0 ? parentRow.Bottom : parentRow.Top;
int view_height = parentRow.Height;
location[0] = (x / MainActivity.Current.Resources.DisplayMetrics.Density);
location[1] = y / MainActivity.Current.Resources.DisplayMetrics.Density;
//send current cell
cellElement.InvokeOnCellItemLongClicked((cellItem.Element as ViewCell).View, location);
listView.Scroll += ListView_Scroll;
return true;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (listView != null)
{
listView.Scroll -= ListView_Scroll;
}
}
private void ListView_Scroll(object sender, Android.Widget.AbsListView.ScrollEventArgs e)
{
cellElement.InvokeOnCellItemTouched(cellElement.View, EventArgs.Empty);
}
//return false if you have not handled it and/or the event should continue to any other on-click listeners.
public bool OnTouch(Android.Views.View v, MotionEvent e)
{
if (e.Action == MotionEventActions.Down)
{
cellElement.InvokeOnCellItemTouched(cellElement.View, EventArgs.Empty);
//cellCore.SetOnTouchListener(this);
}
return false;
}
}
}
}
iOS 渲染器
class SAUITableViewCell : UITableViewCell
{
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
}
}
//When you scroll, your cells are created in real time. cells aren't created from scratch, instead iOS just takes a cell that has just left the screen and sends it through
class SAChatViewCellRenderer : ViewCellRenderer, IUIGestureRecognizerDelegate
{
UITableView TV;
SAChatViewCell cellElement;
public IntPtr Handle => new IntPtr();
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
try
{
UITableViewCell cell = base.GetCell(item, reusableCell, tv);
TV = tv;
var uiTapGestureRecognize = new UITapGestureRecognizer(OnClick);
var uiLongPressGestureRecognizer = new UILongPressGestureRecognizer(OnLongClick);
uiLongPressGestureRecognizer.MinimumPressDuration = 0.5;
cell.AddGestureRecognizer(uiTapGestureRecognize);
cell.AddGestureRecognizer(uiLongPressGestureRecognizer);
cellElement = item as SAChatViewCell;
cell.BackgroundColor = UIColor.Clear;
if (cellElement.SelectedBackgroundColor == Color.Transparent)
{
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
}
else
{
cell.SelectedBackgroundView = new UIView
{
BackgroundColor = cellElement.SelectedBackgroundColor.ToUIColor() ?? default(UIColor)
};
}
return cell;
}
catch (Exception ex)
{
throw ex;
}
}
private void OnLongClick(UILongPressGestureRecognizer arg)
{
//get the current touch coords based on listview
CGPoint coords = arg.LocationInView(TV);
//current cell
if (arg.State != UIGestureRecognizerState.Began)
{
var indexPath = TV.IndexPathForRowAtPoint(coords);
CGRect Rect = TV.RectForRowAtIndexPath(indexPath);
//delete the listview offset
Rect.Offset(-TV.ContentOffset.X, -TV.ContentOffset.Y);
var CurrentViewCell = (arg.View as UIKit.UITableViewCell).Superview;
//Note : xamarin forms cell element MonoTouch creates it's own internal delegate type for UIScrollView so we either override the uiviewtable or trigger the ondisappear event
var cellItem = arg.View as INativeElementView;
(((cellItem.Element as ViewCell).Parent) as ListView).ItemDisappearing += (s, o) =>
{
cellElement.InvokeOnCellItemTouched(cellElement.View, EventArgs.Empty);
};
float[] location = new float[] { 0, 0 };
location[0] = (float)Rect.X;
var Y = Rect.Top <= 0 ? Rect.Bottom : Rect.Top;
location[1] = (float)Y;
cellElement.InvokeOnCellItemLongClicked((cellItem.Element as ViewCell).View, location);
}
}
private void OnClick()
{
cellElement.InvokeOnCellItemTouched(cellElement.View, EventArgs.Empty);
}
public void Dispose()
{
throw new NotImplementedException();
}
}
}