各タブが 1 種類の製品 (ピザ製品など) を保持し、このタブから特定の製品 (マルゲリータ) を注文に追加できるようにする、いくつかのタブで構成される小さなアプリケーションを開発しています。各タブには、左側に各製品を表すボタンがあり、右側に現在注文に追加されているアイテム (すべての製品) + 計算された価格のリストがあるレイアウトが保持されます。Tab
これは私が現在追加する方法ですTabHost
:
Bundle extras = new Bundle();
extras.putString("productType", "pizza");
tabHost.addTab(tabHost.newTabSpec("pizza").setIndicator("Pizza"), OrderFragment.class, extras);
問題は、OrderFragment のコンストラクターで引数を取得しようとすると、例外がスローされることです。
E/AndroidRuntime(533): FATAL EXCEPTION: main
E/AndroidRuntime(533): java.lang.NullPointerException
OrderFragment にデータを渡す必要がある理由は、OrderFragment があらゆる種類の製品 (製品、パスタなど) の抽象クラスになるためです。そのための適切なデータをロードします。このメソッドaddTab(TabSpec, Class<T>, Bundle)
は指定されたクラスのインスタンスを作成し、そこにエクストラを入れると思っていましたが、これらのエクストラはパックされていないようです。(それは別の目的のためだと思います)。これを解決する方法について何か提案をいただければ幸いです。全く違うやり方でしたら、その点もご指摘いただければ幸いです。
オーダーフラグメント:
public class OrderFragment extends Fragment implements IEditOrder{
private static final String TAG = "OrderFragment";
private Controller controller;
private ListView lst_order;
private TextView txt_order_total;
private Button btn_finishOrder;
private Button btn_cancelOrder;
private String productType;
private OrderAdapter orderAdapter;
private static final int DIALOG_EDIT_ORDER = 1;
public OrderFragment() {
Bundle extras = getArguments();
Log.d(TAG, "Extras: " + extras.toString());
this.productType = extras.getString("productType");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//setRetainInstance(true);
controller = Controller.getInstance();
controller.loadProducts(getActivity().getApplicationContext());
//FillDatabase.loadDataToDatabase(getActivity());
}
@Override
public void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pizza, container, false);
txt_order_total = (TextView)view.findViewById(R.id.txt_order_total);
btn_finishOrder = (Button)view.findViewById(R.id.btn_finishOrder);
btn_cancelOrder = (Button)view.findViewById(R.id.btn_cancelOrder);
btn_finishOrder.setOnClickListener(finishOrder);
btn_cancelOrder.setOnClickListener(cancelOrder);
final RelativeLayout layout = (RelativeLayout) view.findViewById(R.id.rl_order_pizza);
orderAdapter = new OrderAdapter(getActivity(), controller.getOrderMap());
lst_order = (ListView) view.findViewById(R.id.lst_order);
lst_order.addHeaderView(inflater.inflate(R.layout.order_list_header, null));
lst_order.setAdapter(orderAdapter);
lst_order.setOnItemClickListener(itemClickListener);
txt_order_total.setText("Total Price: " + controller.calculateTotalPrice());
layout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
RelativeLayout.LayoutParams layoutParams;
int currentX = 20;
int currentY = 20;
for (Product product: controller.getProducts("pizza")){
layoutParams = new RelativeLayout.LayoutParams(UIConstnts.BUTTON_WIDTH, UIConstnts.BUTTON_HEIGHT);
Button tempButton = new Button(getActivity().getApplicationContext());
tempButton.setId((int)product.getId());
tempButton.setText(product.getName());
tempButton.setOnClickListener(clickListener);
layoutParams.setMargins(currentX, currentY, 0, 0);
tempButton.setLayoutParams(layoutParams);
layout.addView(tempButton);
if (layout.getWidth() < currentX + UIConstnts.MARGIN_LEFT + (2 * UIConstnts.BUTTON_WIDTH)){
currentX = 20;
currentY += UIConstnts.BUTTON_HEIGHT + UIConstnts.MARGIN_BOTTOM;
}
else{
currentX += UIConstnts.MARGIN_LEFT + UIConstnts.BUTTON_WIDTH;
}
}
layout.requestLayout();
}
});
return view;
}
private OnClickListener clickListener = new OnClickListener(){
@Override
public void onClick(View view) {
controller.addOrderItem(1, (long)view.getId());
updateQuantity();
txt_order_total.setText("Total Price: " + controller.calculateTotalPrice());
}
};
private OnItemClickListener itemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
showDialog(id, Integer.valueOf(((TextView)view.findViewById(R.id.txt_lst_quantity)).getText().toString()));
}
};
private OnClickListener finishOrder = new OnClickListener(){
@Override
public void onClick(View v) {
controller.finishOrder(getActivity());
updateQuantity();
}
};
private OnClickListener cancelOrder = new OnClickListener(){
@Override
public void onClick(View v) {
controller.resetOrder();
updateQuantity();
}
};
private void showDialog(long productId, int quantity) {
DialogFragment newFragment = EditOrderDialog.newInstance(productId, quantity, "Change Quantity");
newFragment.setTargetFragment(this, DIALOG_EDIT_ORDER);
newFragment.show(getFragmentManager(), "dialog");
}
@Override
public void updateQuantity() {
orderAdapter.setOrderList(controller.getOrderMap());
orderAdapter.notifyDataSetChanged();
txt_order_total.setText("Total Price: " + controller.calculateTotalPrice());
}
}
UIの写真。(右側の ListView はすべてのタブに表示され、注文のすべての製品が含まれています):