【发布时间】:2019-12-23 17:04:43
【问题描述】:
我正在尝试将 Java 代码转换为 C# 以下是我目前所得到的:
MainActivity.cs
public class MainActivity : AppCompatActivity
{
private RecyclerView recyclerViewOrders;
private OrderAdapter recyclerViewAdapterOrders;
private RecyclerView recyclerViewPackages;
private PackageAdapter recyclerViewAdapterPackages;
private RecyclerView.LayoutManager layoutManagerOrders;
private RecyclerView.LayoutManager layoutManagerPackages;
private List<OrderData> ordersList = new List<OrderData>();
private List<PackageData> packageList = new List<PackageData>();
SwipeToDeleteCallback swipeToDeleteCallback = null;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
recyclerViewOrders = (RecyclerView)FindViewById(Resource.Id.RecyclerViewOrders);
recyclerViewPackages = (RecyclerView)FindViewById(Resource.Id.RecyclerViewPackages);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerViewOrders.HasFixedSize = true;
recyclerViewPackages.HasFixedSize = true;
// use a linear layout manager
layoutManagerOrders = new LinearLayoutManager(this);
recyclerViewOrders.SetLayoutManager(layoutManagerOrders);
layoutManagerPackages = new LinearLayoutManager(this);
recyclerViewPackages.SetLayoutManager(layoutManagerPackages);
// specify an adapter (see also next example)
//recyclerViewAdapter = new MyAdapter(myDataset);
ordersList.Add(new OrderData { Order = "Order 1" });
ordersList.Add(new OrderData { Order = "Order 2" });
ordersList.Add(new OrderData { Order = "Order 3" });
ordersList.Add(new OrderData { Order = "Order 4" });
ordersList.Add(new OrderData { Order = "Order 5" });
recyclerViewAdapterOrders = new OrderAdapter(ordersList);
recyclerViewOrders.SetAdapter(recyclerViewAdapterOrders);
packageList.Add(new PackageData { Package = "Package 1" });
packageList.Add(new PackageData { Package = "Package 2" });
packageList.Add(new PackageData { Package = "Package 3" });
packageList.Add(new PackageData { Package = "Package 4" });
packageList.Add(new PackageData { Package = "Package 5" });
recyclerViewAdapterPackages = new PackageAdapter(packageList);
recyclerViewPackages.SetAdapter(recyclerViewAdapterPackages);
//SwipeToDeleteCallback swipeHandlerOrder = new SwipeToDeleteCallback(0, ItemTouchHelper.Left, this, recyclerViewAdapterOrders);
SwipeToDeleteCallback swipeHandlerOrder = new SwipeToDeleteCallback(this, recyclerViewAdapterOrders);
ItemTouchHelper itemTouchHelperOrder = new ItemTouchHelper(swipeHandlerOrder);
itemTouchHelperOrder.AttachToRecyclerView(recyclerViewOrders);
//SwipeToDeleteCallback swipeHandlerPackage = new SwipeToDeleteCallback(0, ItemTouchHelper.Left, this, recyclerViewAdapterPackages);
//ItemTouchHelper itemTouchHelperPackage = new ItemTouchHelper(swipeHandlerPackage);
//itemTouchHelperPackage.AttachToRecyclerView(recyclerViewPackages);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
下面是我的 OrderAdapter.cs:
// ADAPTER
// Adapter to connect the data set (orders) to the RecyclerView:
public class OrderAdapter : RecyclerView.Adapter
{
// Event handler for item clicks:
public event EventHandler<int> ItemClick;
// Underlying data set (order):
private List<OrderData> listOrderData; //= new List<OrderData>()
// Load the adapter with the data set (order data) at construction time:
public OrderAdapter(List<OrderData> orderData)
{
listOrderData = orderData;
}
// Create a new order CardView (invoked by the layout manager):
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
// Inflate the CardView for the order:
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.OrdersCardView, parent, false);
// Create a ViewHolder to find and hold these view references, and
// register OnClick with the view holder:
return new OrderViewHolder(itemView, OnClick);
}
// Fill in the contents of the order list (invoked by the layout manager):
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
OrderViewHolder vh = holder as OrderViewHolder;
// Set the TextView in this ViewHolder's CardView
// from this position in the order list:
vh.Order.SetText(listOrderData[position].Order, null);
}
// Return the number of orders available in the order list:
public override int ItemCount
{
get { return listOrderData.Count; }
}
// Raise an event when the item-click takes place:
void OnClick(int position) { ItemClick?.Invoke(this, position); }
public void RemoveItem(int position)
{
listOrderData.RemoveAt(position);
NotifyItemChanged(position);
NotifyItemRemoved(position);
NotifyDataSetChanged();
}
}
请看下面我的 SwipeToDeleteCallback.cs:
enum ButtonsState
{
GONE,
LEFT_VISIBLE,
RIGHT_VISIBLE
}
public class SwipeToDeleteCallback : ItemTouchHelper.SimpleCallback, View.IOnTouchListener
{
private OrderAdapter orderAdapter;
private Context context;
public static bool swipeBack = false;
private ButtonsState buttonShowedState = ButtonsState.GONE;
private RectF buttonInstance = null;
private RecyclerView.ViewHolder currentItemViewHolder = null;
private SwipeControllerActions buttonsActions = null;
private static float buttonWidth = 300;
public SwipeToDeleteCallback(SwipeControllerActions buttonsActions) : base(ItemTouchHelper.ActionStateIdle, ItemTouchHelper.Down)
{
this.buttonsActions = buttonsActions;
}
public SwipeToDeleteCallback(Context context, OrderAdapter orderAdapter) : base(ItemTouchHelper.ActionStateIdle, ItemTouchHelper.Down)
{
this.context = context;
this.orderAdapter = orderAdapter;
}
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return MakeMovementFlags(0, ItemTouchHelper.Left); }
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; }
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction) { }
public override int ConvertToAbsoluteDirection(int flags, int layoutDirection)
{
if (swipeBack)
{
swipeBack = buttonShowedState != ButtonsState.GONE;
return 0;
}
return base.ConvertToAbsoluteDirection(flags, layoutDirection);
}
public override void OnChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive)
{
if (actionState == ItemTouchHelper.ActionStateSwipe)
{
if (buttonShowedState != ButtonsState.GONE)
{
if (buttonShowedState == ButtonsState.LEFT_VISIBLE) dX = Math.Max(dX, buttonWidth);
if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) dX = Math.Min(dX, -buttonWidth);
base.OnChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
else
{
SetTouchListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
if (buttonShowedState == ButtonsState.GONE)
{
base.OnChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
currentItemViewHolder = viewHolder;
}
private void SetTouchListener(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive)
{
recyclerView.SetOnTouchListener(this);
if (swipeBack)
{
if (dX < -buttonWidth) { buttonShowedState = ButtonsState.RIGHT_VISIBLE; }
if (dX > buttonWidth) { buttonShowedState = ButtonsState.LEFT_VISIBLE; }
if (buttonShowedState != ButtonsState.GONE)
{
SetTouchDownListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
SetItemsClickable(recyclerView, false);
}
}
}
private void SetTouchDownListener( Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive )
{
recyclerView.SetOnTouchListener(this);
SetTouchUpListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
private void SetTouchUpListener( Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive )
{
base.OnChildDraw(c, recyclerView, viewHolder, 0F, dY, actionState, isCurrentlyActive);
recyclerView.SetOnTouchListener(this);
SetItemsClickable(recyclerView, true);
swipeBack = false;
if (buttonShowedState == ButtonsState.LEFT_VISIBLE)
{
buttonsActions.OnLeftClicked(viewHolder.AdapterPosition);
}
else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE)
{
buttonsActions.OnRightClicked(viewHolder.AdapterPosition);
}
buttonShowedState = ButtonsState.GONE;
currentItemViewHolder = null;
}
private void SetItemsClickable(RecyclerView recyclerView, bool isClickable)
{
for (int i = 0; i < recyclerView.ChildCount; ++i)
{
recyclerView.GetChildAt(i).Clickable = isClickable;
}
}
private void DrawButtons(Canvas c, RecyclerView.ViewHolder viewHolder)
{
float buttonWidthWithoutPadding = buttonWidth - 20;
float corners = 16;
View itemView = viewHolder.ItemView;
Paint p = new Paint();
RectF leftButton = new RectF(itemView.Left, itemView.Top, itemView.Left + buttonWidthWithoutPadding, itemView.Bottom);
p.Color = Color.Blue;
c.DrawRoundRect(leftButton, corners, corners, p);
DrawText("EDIT", c, leftButton, p);
RectF rightButton = new RectF(itemView.Right - buttonWidthWithoutPadding, itemView.Top, itemView.Right, itemView.Bottom);
p.Color = Color.Red;
c.DrawRoundRect(rightButton, corners, corners, p);
DrawText("DELETE", c, rightButton, p);
buttonInstance = null;
if (buttonShowedState == ButtonsState.LEFT_VISIBLE)
{
buttonInstance = leftButton;
}
else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE)
{
buttonInstance = rightButton;
}
}
private void DrawText(String text, Canvas c, RectF button, Paint p)
{
float textSize = 60;
p.Color = Color.White;
p.AntiAlias = true;
p.TextSize = textSize;
float textWidth = p.MeasureText(text);
c.DrawText(text, button.CenterX() - (textWidth / 2), button.CenterY() + (textSize / 2), p);
}
public void OnDraw(Canvas c)
{
if (currentItemViewHolder != null)
{
DrawButtons(c, currentItemViewHolder);
}
}
public bool OnTouch(View v, MotionEvent ev)
{
swipeBack = ev.Action == MotionEventActions.Cancel || ev.Action == MotionEventActions.Up;
if (ev.Action == MotionEventActions.Down)
{
return true;
}
if (ev.Action == MotionEventActions.Up)
{
if (buttonsActions != null && buttonInstance != null && buttonInstance.Contains(ev.GetX(), ev.GetY()))
{
return true;
}
return false;
}
return false;
}
}
最后是我的 SwipeControllerActions.cs:
public abstract class SwipeControllerActions
{
public void OnLeftClicked(int position) { }
public void OnRightClicked(int position) { }
}
因为 C# 不使用匿名类,所以我在实现 OnTouch 时遇到了困难。 我将在下面发布 Java 中的原始代码:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private PlayersDataAdapter mAdapter;
SwipeController swipeController = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setPlayersDataAdapter();
setupRecyclerView();
}
private void setPlayersDataAdapter() {
List<Player> players = new ArrayList<>();
try {
InputStreamReader is = new InputStreamReader(getAssets().open("players.csv"));
BufferedReader reader = new BufferedReader(is);
reader.readLine();
String line;
String[] st;
while ((line = reader.readLine()) != null) {
st = line.split(",");
Player player = new Player();
player.setName(st[0]);
player.setNationality(st[1]);
player.setClub(st[4]);
player.setRating(Integer.parseInt(st[9]));
player.setAge(Integer.parseInt(st[14]));
players.add(player);
}
} catch (IOException e) {
}
mAdapter = new PlayersDataAdapter(players);
}
private void setupRecyclerView() {
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(mAdapter);
swipeController = new SwipeController(new SwipeControllerActions() {
@Override
public void onRightClicked(int position) {
mAdapter.players.remove(position);
mAdapter.notifyItemRemoved(position);
mAdapter.notifyItemRangeChanged(position, mAdapter.getItemCount());
}
});
ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeController);
itemTouchhelper.attachToRecyclerView(recyclerView);
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
swipeController.onDraw(c);
}
});
}
}
SwipeController.java:
enum ButtonsState {
GONE,
LEFT_VISIBLE,
RIGHT_VISIBLE
}
类 SwipeController 扩展回调 {
private boolean swipeBack = false;
private ButtonsState buttonShowedState = ButtonsState.GONE;
private RectF buttonInstance = null;
private RecyclerView.ViewHolder currentItemViewHolder = null;
private SwipeControllerActions buttonsActions = null;
private static final float buttonWidth = 300;
public SwipeController(SwipeControllerActions buttonsActions) {
this.buttonsActions = buttonsActions;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(0, LEFT | RIGHT);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
if (swipeBack) {
swipeBack = buttonShowedState != ButtonsState.GONE;
return 0;
}
return super.convertToAbsoluteDirection(flags, layoutDirection);
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ACTION_STATE_SWIPE) {
if (buttonShowedState != ButtonsState.GONE) {
if (buttonShowedState == ButtonsState.LEFT_VISIBLE) dX = Math.max(dX, buttonWidth);
if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) dX = Math.min(dX, -buttonWidth);
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
else {
setTouchListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
if (buttonShowedState == ButtonsState.GONE) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
currentItemViewHolder = viewHolder;
}
private void setTouchListener(final Canvas c, final RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder, final float dX, final float dY, final int actionState, final boolean isCurrentlyActive) {
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
swipeBack = event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP;
if (swipeBack) {
if (dX < -buttonWidth) buttonShowedState = ButtonsState.RIGHT_VISIBLE;
else if (dX > buttonWidth) buttonShowedState = ButtonsState.LEFT_VISIBLE;
if (buttonShowedState != ButtonsState.GONE) {
setTouchDownListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
setItemsClickable(recyclerView, false);
}
}
return false;
}
});
}
private void setTouchDownListener(final Canvas c, final RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder, final float dX, final float dY, final int actionState, final boolean isCurrentlyActive) {
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setTouchUpListener(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
return false;
}
});
}
private void setTouchUpListener(final Canvas c, final RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder, final float dX, final float dY, final int actionState, final boolean isCurrentlyActive) {
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
SwipeController.super.onChildDraw(c, recyclerView, viewHolder, 0F, dY, actionState, isCurrentlyActive);
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
setItemsClickable(recyclerView, true);
swipeBack = false;
if (buttonsActions != null && buttonInstance != null && buttonInstance.contains(event.getX(), event.getY())) {
if (buttonShowedState == ButtonsState.LEFT_VISIBLE) {
buttonsActions.onLeftClicked(viewHolder.getAdapterPosition());
}
else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) {
buttonsActions.onRightClicked(viewHolder.getAdapterPosition());
}
}
buttonShowedState = ButtonsState.GONE;
currentItemViewHolder = null;
}
return false;
}
});
}
private void setItemsClickable(RecyclerView recyclerView, boolean isClickable) {
for (int i = 0; i < recyclerView.getChildCount(); ++i) {
recyclerView.getChildAt(i).setClickable(isClickable);
}
}
private void drawButtons(Canvas c, RecyclerView.ViewHolder viewHolder) {
float buttonWidthWithoutPadding = buttonWidth - 20;
float corners = 16;
View itemView = viewHolder.itemView;
Paint p = new Paint();
RectF leftButton = new RectF(itemView.getLeft(), itemView.getTop(), itemView.getLeft() + buttonWidthWithoutPadding, itemView.getBottom());
p.setColor(Color.BLUE);
c.drawRoundRect(leftButton, corners, corners, p);
drawText("EDIT", c, leftButton, p);
RectF rightButton = new RectF(itemView.getRight() - buttonWidthWithoutPadding, itemView.getTop(), itemView.getRight(), itemView.getBottom());
p.setColor(Color.RED);
c.drawRoundRect(rightButton, corners, corners, p);
drawText("DELETE", c, rightButton, p);
buttonInstance = null;
if (buttonShowedState == ButtonsState.LEFT_VISIBLE) {
buttonInstance = leftButton;
}
else if (buttonShowedState == ButtonsState.RIGHT_VISIBLE) {
buttonInstance = rightButton;
}
}
private void drawText(String text, Canvas c, RectF button, Paint p) {
float textSize = 60;
p.setColor(Color.WHITE);
p.setAntiAlias(true);
p.setTextSize(textSize);
float textWidth = p.measureText(text);
c.drawText(text, button.centerX()-(textWidth/2), button.centerY()+(textSize/2), p);
}
public void onDraw(Canvas c) {
if (currentItemViewHolder != null) {
drawButtons(c, currentItemViewHolder);
}
}
}
最后是 SwipeControllerActions.java:
public abstract class SwipeControllerActions {
public void onLeftClicked(int position) {}
public void onRightClicked(int position) {}
}
我可以让项目滑动,但无法显示文本或按钮区域。 任何帮助将不胜感激。
【问题讨论】:
标签: java c# android-recyclerview ontouch