简体   繁体   中英

Android: add a new item to a list and display it via RecyclerView adapter using Kotlin

I have a fragment that has a RecyclerView. When the user clicks a button (ADD NEW ITEM) in the fragment, the app takes the user (via intent) to a form to fill-in some data.

When I click on (ADD ITEM), it should add the data to the array list and finish that screen. After going back to the fragment, this data should be added to the RecyclerView using the adapter.

This is my code:

Here is the fragment:

private val REQUEST_CODE = 2

internal lateinit var adapter: ShipmentItemAdapter

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    return inflater!!.inflate(R.layout.fragment_step_three_shipment, container, false)
}

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    btnAddNewShipmentStep3.setOnClickListener {
        val intent = Intent(context, AddItemActivity::class.java)
        startActivityForResult(intent, REQUEST_CODE)
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data);

    val items = ArrayList<ItemsItem>()

    if (requestCode == REQUEST_CODE) {

        adapter = ShipmentItemAdapter(context, items)

        if (resultCode == Activity.RESULT_OK) {
            itemsShipments.visibility = View.VISIBLE
            itemsShipments.layoutManager = LinearLayoutManager(context)
            itemsShipments.setHasFixedSize(true)
            itemsShipments.adapter = adapter

        } else if (resultCode == Activity.RESULT_CANCELED) {
            itemsShipments.visibility = View.GONE
        }
    }
}

And here is the activity:

class AddItemActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_add_item_form)

    linPackageAddShipment.setOnClickListener {
        edtPackageAddShipment.requestFocus()
    }

    linPiecesAddShipment.setOnClickListener {
        edtPiecesAddShipment.requestFocus()
    }

    linWeightAddShipment.setOnClickListener {
        edtWeightAddShipment.requestFocus()
    }

    linDescriptionAddShipment.setOnClickListener {
        edtDescriptionAddShipment.requestFocus()
    }


    btnAddItemAddShipment.setOnClickListener {
        val errors = collectData()

        collectData()

        if (errors.isEmpty()) {

            val intent = Intent()
            setResult(Activity.RESULT_OK, intent)
            finish()

        } else {
            val errorBody = errors.map { getString(it) }.joinToString("\n") { it }
            MaterialDialog.Builder(this)
                    .title("Oops")
                    .content(errorBody)
                    .positiveText(R.string.ok)
                    .positiveColor(ContextCompat.getColor(this, R.color.colorPrimary))
                    .onAny({ dialog, _ -> dialog.dismiss() })
                    .show()
        }
    }
  }

  private fun collectData(): ArrayList<Int> {
    val errors = ArrayList<Int>()
    val item = ItemsItem()

    if (edtPackageAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.packages_must_not_be_empty)

    } else {
        item.numberOfPackages = edtPackageAddShipment.text.toString().toInt()
    }

    if (edtPiecesAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.pieces_must_not_be_empty)

    } else {
        item.numberOfPieces = edtPiecesAddShipment.text.toString()
    }

    if (edtWeightAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.weight_must_not_be_empty)

    } else {
        item.weightUnit = edtWeightAddShipment.text.toString().toInt()
    }

    if (edtHeightAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.height_must_not_be_empty)

    } else {
        item.height = edtHeightAddShipment.text.toString()
    }

    if (edtWidthAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.width_must_not_be_empty)

    } else {
        item.width = edtWidthAddShipment.text.toString()
    }
    if (edtLengthAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.length_must_not_be_empty)

    } else {
        item.length = edtLengthAddShipment.text.toString()
    }

    if (edtDescriptionAddShipment.text.toString().isEmpty()) {
        errors.add(R.string.description_must_not_be_empty)

    } else {
        item.description = edtDescriptionAddShipment.text.toString()
    }

    CreateNewShipmentActivity.mainShipment.shipmentObj.items?.add(item)

    return errors
  }

  override fun onBackPressed() {
    setResult(Activity.RESULT_CANCELED)
    super.onBackPressed()
  }
}

Here is the adapter:

class ShipmentItemAdapter internal constructor(private val context: Context, private val items: List<ItemsItem>) : RecyclerView.Adapter<ShipmentItemAdapter.MyViewHolder>() {

  private val inflater: LayoutInflater = LayoutInflater.from(context)


  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val view = inflater.inflate(R.layout.item_shipment_package, parent, false)

    return MyViewHolder(view).listen { pos, type ->
        val item = items[pos]
        val intent = Intent(context, AddItemActivity::class.java)
        startActivity(context, intent, null)
    }
  }


  override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.namePackageShipmentPackage.text = items[position].description
    holder.quantityPackageShipmentPackage.text = items[position].description
    holder.dimensionPackageHeightShipmentPackage.text = items[position].description
    holder.dimensionPackageWidthShipmentPackage.text = items[position].description
    holder.dimensionPackageLengthShipmentPackage.text = items[position].description

  }

  override fun getItemCount(): Int {
    return items.size
  }

  inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    var namePackageShipmentPackage: AppCompatTextView = itemView.findViewById(R.id.namePackageShipmentPackage)
    var quantityPackageShipmentPackage: AppCompatTextView = itemView.findViewById(R.id.quantityPackageShipmentPackage)
    var dimensionPackageHeightShipmentPackage: AppCompatTextView = itemView.findViewById(R.id.dimensionPackageHeightShipmentPackage)
    var dimensionPackageWidthShipmentPackage: AppCompatTextView = itemView.findViewById(R.id.dimensionPackageWidthShipmentPackage)
    var dimensionPackageLengthShipmentPackage: AppCompatTextView = itemView.findViewById(R.id.dimensionPackageLengthShipmentPackage)


  }

  private fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
    itemView.setOnClickListener {
        event.invoke(adapterPosition, itemViewType)
    }
    return this
  }

These are the object model:

class ShipmentObj {
    var items: ArrayList<ItemsItem?>? = null
}


data class ItemsItem(
    var numberOfPieces: String? = null,
    var length: String? = null,
    var description: String? = null,
    var numberOfPackages: Int? = null,
    var number: Int? = null,
    var width: String? = null,
    var height: String? = null,
    var weightUnit: Int? = null
)

When I try to add new item nothing is showing in the fragment! I don't now where is the mistake?

Thanks.

You need to add first in your adapter one function for adding new items to Array, in your case is "items: List":

First step:

  • In your adapter ShipmentItemAdapter add the next fun

 fun addNewItem(itemsNew: List<ItemsItem>){ items.clear() // ->> optional if you need have clear of object items.addAll(itemsNew) notifyDataSetChanged() }

then, in your fragment in onActivityResult when you receive the Activity.RESULT_OK you might add the new item

 adapter.addNewItem(itemsNew)

In the onActivityResult you can see the error in your code You do something like this

val items = ArrayList<ItemsItem>()
adapter = ShipmentItemAdapter(context, items)

You assign to the adapter, an empty list of items. And if i'm not wrong, you don't pass the item that you want to send either.

 if (errors.isEmpty()) {
        val intent = Intent()
        setResult(Activity.RESULT_OK, intent)
        finish()
 }

You finish the activity without passing any item as a result. The previous activity doesn't receive anything. I can't execute you code because I don't have all the elements to execute it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM