我有一个片段正在处理物品的“制作”,它显示了一个“制作台”,一个物品的成本列表和一个库存。在片段的第一次初始化时,制作台工作正常,但在我替换它之后,第四次,当我制作时,它不会更新(点击工艺按钮)。
下面是一个例子:Example Video
我试过用written.Post Package 一些函数,但没有用。
碎片:
using Android.Graphics;
using Android.OS;
using Android.Views;
using Android.Widget;
using AndroidX.Fragment.App;
using MineClick.Crafting.Bench;
using MineClick.Crafting.Bench.CostList;
using MineClick.EventSystem;
using MineClick.EventSystem.EventArguments;
using MineClick.Materials;
using MineClick.Navigation;
using MineClick.Pickaxes;
using MineClick.Player;
using MineClick.Utility;
using static MineClick.EventSystem.EventManager;
using static MineClick.InventoryView;
namespace MineClick.Crafting
{
internal class CraftFragment : Fragment
{
CraftAdapter CraftAdapter { get; set; }
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.Inflate(Resource.Layout.crafting_activity, container, false);
LinearLayout wrraper = view.FindViewById<LinearLayout>(Resource.Id.crafting_wrraper);
LinearLayout inventoryWrraper = view.FindViewById<LinearLayout>(Resource.Id.inventory_wrraper);
LinearLayout costListWrraper = view.FindViewById<LinearLayout>(Resource.Id.cost_list_wrraper);
CraftingBench bench = new CraftingBench(Context);
wrraper.AddView(bench);
InventoryView inventoryDisplay = new InventoryView(Context, PlayerApplication.Instance.Player.PlayerInventory);
inventoryWrraper.AddView(inventoryDisplay);
CostListView costList = new CostListView(Context);
costListWrraper.AddView(costList);
CraftAdapter = new CraftAdapter(inventoryDisplay, bench,costList);
return view;
}
}
}
字符串
Craft适配器:
using Android.Widget;
using MineClick.Crafting.Bench.CostList;
using MineClick.Crafting.Recipes.Handlers;
using MineClick.EventSystem;
using MineClick.Materials;
using MineClick.Player;
using static MineClick.EventSystem.EventManager;
using static MineClick.InventoryView;
namespace MineClick.Crafting
{
internal class CraftAdapter
{
InventoryView InvView;
RecipeAdapter BenchAdapter;
public CraftAdapter(InventoryView invView, CraftingBench bench, CostListView costList)
{
InvView = invView;
BenchAdapter = new RecipeAdapter(bench,costList);
Initialize();
}
private void Initialize()
{
InvView.OnClickActions = OnInvClick;
EventManager.BindListener(Events.ITEM_CRAFTED, (sender, args) => OnCraft(args.CraftedItem));
}
public void OnInvClick(InventoryClickEvent e)
{
if (e.ClickedItem.DisplayedItem == null)
return;
Item itemToAdd = ItemRegistry.GetItemById(e.ClickedItem.DisplayedItem.GetItem().Id);
bool add = BenchAdapter.OnAttemptAddItem(itemToAdd.Clone());
// Do something if add failed (toast or something)
if(!add)
Toast.MakeText(e.ClickedItem.Context, "Cannot Add Item To Bench",ToastLength.Long);
}
public void OnCraft(Item item)
{
PlayerApplication.Instance.Player.PlayerInventory.Add(item);
BenchAdapter.Reset();
InvView.Update();
}
}
}
型
Recipe适配器:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using MineClick.Crafting.Bench;
using MineClick.Crafting.Bench.CostList;
using MineClick.EventSystem;
using MineClick.EventSystem.EventArguments;
using MineClick.Materials;
using MineClick.Player;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static MineClick.EventSystem.EventManager;
namespace MineClick.Crafting.Recipes.Handlers
{
internal class RecipeAdapter
{
public CraftingBench Bench { get; set; }
public RecipeManager Manager { get; set; }
public CostListView CostList;
public RecipeAdapter(CraftingBench bench, CostListView costList,Item defaultMainItem,Item[] defaultExtras)
{
Manager = new RecipeManager(defaultMainItem,defaultExtras);
Bench = bench;
CostList = costList;
CostList.CButton.Click += (sender, args) => Craft();
Update();
}
public RecipeAdapter(CraftingBench bench, CostListView costList)
{
Manager = new RecipeManager();
Bench = bench;
CostList = costList;
CostList.CButton.Click += (sender, args) => Craft();
Update();
}
public bool OnAttemptAddItem(Item item)
{
if (Manager.AttemptAddItem(item))
Update();
else return false;
return true;
}
public void Update()
{
Bench.UpdateBench(Manager.MainItem, Manager.Extras, Manager.GetResultDisplay(Bench.Context));
UpdateCostList();
}
private void UpdateCostList()
{
Dictionary<Item, bool> costList = new Dictionary<Item, bool>();
Inventory inventory = PlayerApplication.Instance.Player.PlayerInventory;
if(Manager.CalculateCost() != null)
Manager.CalculateCost().ForEach(item =>
{
bool valid = true;
if (!inventory.Contains(item.Id))
valid = false;
else if (item is CountableItem)
valid = ((CountableItem)item).Amount <= ((CountableItem)inventory.Get(item.Id)).Amount;
costList.Add(item, valid);
});
CostList.Recycler.Adapter.SetItems(costList);
CostList.CButton.Valid = costList.All(entry => entry.Value);
CostList.CButton.Visibility = costList.Count == 0 ? ViewStates.Invisible : ViewStates.Visible;
}
private void Craft()
{
Item crafted = Manager.CalculateResult();
if (CostList.CButton.Valid)
EventManager.InvokeEvent(Events.ITEM_CRAFTED, new EA_ITEM_CRAFTED(crafted));
}
public void Reset()
{
Manager.Reset();
Update();
}
}
}
型
Recipe Manager:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using MineClick.Materials;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MineClick.Crafting.Recipes.Handlers
{
internal class RecipeManager
{
public static readonly int EXTRAS_AMOUNT = 6;
public Item MainItem { get; private set; }
public Item[] Extras { get; private set; }
IRecipeAcceptor RecipeAcceptor;
public RecipeManager(Item mainItem, Item[] extras)
{
MainItem = mainItem;
Extras = extras;
}
public RecipeManager() : this(null,new Item[EXTRAS_AMOUNT])
{
}
public void SetRecipeItem(Item item)
{
if (item != null && RecipeRegistry.GetRecipeBindings().ContainsKey(item.Id))
{
MainItem = item.Clone();
RecipeAcceptor = RecipeRegistry.GetRecipeBindings()[MainItem.Id];
}
else
{
MainItem = null;
RecipeAcceptor = null;
}
Array.Clear(Extras, 0, Extras.Length);
}
public bool AttemptAddItem(Item item)
{
if (item == null)
return false;
bool success;
if (MainItem == null)
success = AttemptAddItemToMainSlot(item);
else if (GetFirstEmptyExtraSlot() != -1)
success = AttemptAddItemToExtra(item);
else success = false;
return success;
}
private bool AttemptAddItemToMainSlot(Item item)
{
if (!RecipeRegistry.GetRecipeBindings().ContainsKey(item.Id))
return false;
SetRecipeItem(item);
return true;
}
private bool AttemptAddItemToExtra(Item item)
{
if (GetFirstEmptyExtraSlot() == -1)
return false;
if (!RecipeAcceptor.IsExtraFit(MainItem, item, GetPlainExtras()))
return false;
if (GetPlainExtras().Any(x => x.Id == item.Id))
return false;
Extras[GetFirstEmptyExtraSlot()] = item.Clone();
return true;
}
public int GetFirstEmptyExtraSlot()
{
return Array.IndexOf(Extras, null);
}
public View GetResultDisplay(Context context)
{
if (RecipeAcceptor == null)
return null;
return RecipeAcceptor.DisplayResult(MainItem, GetPlainExtras(), context);
}
public Item CalculateResult()
{
if (RecipeAcceptor == null)
return null;
return RecipeAcceptor.CalculateResult(MainItem, GetPlainExtras());
}
public List<Item> CalculateCost()
{
if (RecipeAcceptor == null)
return null;
return RecipeAcceptor.CalculateCost(MainItem, GetPlainExtras());
}
/// <summary>
/// Get extras not as slots array but as a plain list of extras (no null)
/// </summary>
/// <returns></returns>
public Item[] GetPlainExtras()
{
return Extras.Where(x => x != null).ToArray();
}
public void Reset()
{
SetRecipeItem(null);
}
}
}
型
(我没有添加CraftingBench和CostListView,因为它们只被reciper管理器使用,错误不可能在它们中,因为两者都不起作用,但如果需要任何澄清,请告诉我)
真的很感激任何帮助!
1条答案
按热度按时间jfewjypa1#
我已经设法解决了这个问题。正如预期的那样,它是在CraftFragment和CraftAdapter上:每次视图重置时,我都会重置适配器,事件的BindNode仍然会调用前一个视图。因此,在调试时仍然显示输入,但实际上并没有更新当前视图。我暂时解决了这个问题,只在片段中创建一个CraftAdapter示例,并在每次OnViewCreate更新其视图。