Good! I am developing a PDV App where certain buttons are created at runtime.
I do everything between Fragment and Adapter. But, the basic layout is a cardview that will be my button, this cardview is controlled by a recycle. In this particular one, I also use a swipper.
Below follow the codes:
fragment_product.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorLightGray"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="140dp"
android:background="@drawable/customborder"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/productViewItens"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginBottom="60dp"
android:background="@color/colorWhite"
android:orientation="vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="start"
android:textStyle="bold"
android:text="TOTAL" />
<TextView
android:id="@+id/textProdTotal"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:layout_gravity="right"
android:gravity="end"
android:textStyle="bold"
android:text="R$ 0,00" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="start"
android:text="Subtotal" />
<TextView
android:id="@+id/textProdSubTotal"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="end"
android:text="R$ 0,00" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="start"
android:text="Desconto" />
<TextView
android:id="@+id/textProdDes"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="end"
android:text="R$ 0,00" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="start"
android:text="Acréscimo" />
<TextView
android:id="@+id/textProdAcr"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight=".50"
android:gravity="end"
android:text="R$ 0,00" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
product_grid_items.xml (this will be the layout of the buttons that will be created at runtime)
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardViewProduct"
android:layout_width="match_parent"
android:layout_height="@dimen/button_primary_height"
card_view:cardElevation="1dp"
card_view:cardMaxElevation="1dp"
android:layout_marginBottom="1dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
card_view:cardBackgroundColor="@color/colorWhite">
<com.chauthai.swipereveallayout.SwipeRevealLayout
android:id="@+id/prodItemSwipe"
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:mode="same_level"
card_view:dragEdge="right">
<FrameLayout
android:id="@+id/prodSwipedelete_layout"
android:layout_width="110dp"
android:layout_height="70dp"
android:background="@color/colorLightGray">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/prodSwipeDeleteImg"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center"
android:tint="@color/colorDarkGray"
android:src="@drawable/ic_delete_white_24dp" />
<ImageView
android:id="@+id/btnEditProd"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:tint="@color/colorDarkGray"
android:src="@drawable/ic_mode_edit_white_18dp" />
</LinearLayout>
</FrameLayout>
<FrameLayout
android:id="@+id/front_layout"
android:layout_width="match_parent"
android:layout_height="70dp"
android:padding="5dp"
android:background="@android:color/transparent">
<TextView
android:id="@+id/textProdDesc"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:textColor="@color/colorDarkGray"
android:layout_gravity="center|top"
android:paddingTop="2dp"
android:textSize="@dimen/title_size"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="left"
android:layout_marginLeft="5dp"
android:tint="@color/colorDarkGray"
android:src="@drawable/ic_monetization_on_white_18dp" />
<TextView
android:id="@+id/textProdPrice"
android:layout_width="0dp"
android:layout_height="18dp"
android:layout_weight=".25"
android:textColor="@color/colorDarkGray"
android:layout_marginLeft="10dp"
android:layout_gravity="center"
android:textSize="@dimen/title_size" />
<TextView
android:id="@+id/textProdDescAcr"
android:layout_width="0dp"
android:layout_height="18dp"
android:layout_weight=".25"
android:textColor="@color/colorDarkGray"
android:layout_marginLeft="10dp"
android:layout_gravity="right"
android:gravity="center"
android:textSize="@dimen/title_size" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="bottom"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"
android:orientation="horizontal"
>
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="left"
android:layout_marginLeft="5dp"
android:tint="@color/colorDarkGray"
android:src="@drawable/ic_local_offer_white_18dp" />
<TextView
android:id="@+id/textProdQtd"
android:layout_width="match_parent"
android:layout_height="18dp"
android:layout_marginLeft="10dp"
android:textColor="@color/colorDarkGray"
android:layout_gravity="center"
android:gravity="left"
android:textSize="@dimen/title_size" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</com.chauthai.swipereveallayout.SwipeRevealLayout>
</androidx.cardview.widget.CardView>
Productfragment.java (The Product Fragment)
package br.com.mbd.pdvx.Fragments;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Objects;
import br.com.mbd.pdvx.Adapter.ProductItemAdapter;
import br.com.mbd.pdvx.AppFunctions;
import br.com.mbd.pdvx.R;
public class ProductFragment extends Fragment {
private Context mContext;
private Fragment mActivity;
private static RecyclerView mRecyclerView;
private static RecyclerView.LayoutManager mLayoutManager;
private static RecyclerView.Adapter mAdapter;
public static Fragment RefreshSalesFragment;
public static View rootView;
public static TextView textProdTotal;
public static TextView textProdSubTotal;
public static TextView textProdDes;
public static TextView textProdAcr;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_product, container, false);
mContext = Objects.requireNonNull(getContext()).getApplicationContext();
mActivity = ProductFragment.this;
RefreshSalesFragment = this;
try{
mRecyclerView = rootView.findViewById(R.id.productViewItens);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(rootView.getContext(), 1);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new ProductItemAdapter(rootView.getContext(), AppFunctions.selectedListObj);
mRecyclerView.setAdapter(mAdapter);
} catch (Exception e){
Log.e("fragmentProduct error","error ->" + e.getMessage());
}
textProdTotal = rootView.findViewById(R.id.textProdTotal);
textProdSubTotal = rootView.findViewById(R.id.textProdSubTotal);
textProdDes = rootView.findViewById(R.id.textProdDes);
textProdAcr = rootView.findViewById(R.id.textProdAcr);
textProdTotal.setText(String.format("%.3f", AppFunctions.TOTAL_SALES));
textProdSubTotal.setText(String.format("%.3f", (AppFunctions.TOTAL_SALES + AppFunctions.TOTAL_DESC - AppFunctions.TOTAL_ACRS)));
textProdDes.setText(String.format("%.3f", AppFunctions.TOTAL_DESC));
textProdAcr.setText(String.format("%.3f", AppFunctions.TOTAL_ACRS));
return rootView;
}
public static ProductFragment newInstance(){
return new ProductFragment() ;
}
public void refreshFragment() {
Objects.requireNonNull(getActivity()).getSupportFragmentManager().beginTransaction().detach(this).commitNow(); //commitAllowingStateLoss();
getActivity().getSupportFragmentManager().beginTransaction().attach(this).commitNow();//commitAllowingStateLoss();
}
}
Productitemadapter.java ( The Adapter that will be responsible for creating the buttons, connected with the recicleview xml.
package br.com.mbd.pdvx.Adapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import com.chauthai.swipereveallayout.SwipeRevealLayout;
import com.chauthai.swipereveallayout.ViewBinderHelper;
import java.util.List;
import br.com.mbd.pdvx.AppFunctions;
import br.com.mbd.pdvx.Fragments.Dialogs.ProductEditFragment;
import br.com.mbd.pdvx.Fragments.ProductFragment;
import br.com.mbd.pdvx.R;
public class ProductItemAdapter extends RecyclerView.Adapter<ProductItemAdapter.ViewHolder> {
private final ViewBinderHelper viewBinderHelper = new ViewBinderHelper();
private static Context mContext;
private static List<Object[]> mDataSet;
static RecyclerView mRecyclerView;
private static View front_layout;
private static View prodSwipedelete_layout;
private static ImageView prodSwipeDeleteImg;
private static ImageView btnEditProd;
public ProductItemAdapter(Context context, List<Object[]> list){
mContext = context;
mDataSet = list;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public CardView mCardView;
public SwipeRevealLayout prodItemSwipe;
public TextView textProdDesc;
public TextView textProdPrice;
public TextView textProdDescAcr;
public TextView textProdQtd;
public ViewHolder(View v){
super(v);
mCardView = v.findViewById(R.id.cardViewProduct);
mRecyclerView = v.findViewById(R.id.viewSelected);
prodItemSwipe = v.findViewById(R.id.prodItemSwipe);
prodSwipedelete_layout = v.findViewById(R.id.prodSwipedelete_layout);
prodSwipeDeleteImg = v.findViewById(R.id.prodSwipeDeleteImg);
btnEditProd = v.findViewById(R.id.btnEditProd);
front_layout = v.findViewById(R.id.front_layout);
textProdDesc = v.findViewById(R.id.textProdDesc);
textProdPrice = v.findViewById(R.id.textProdPrice);
textProdDescAcr = v.findViewById(R.id.textProdDescAcr);
textProdQtd = v.findViewById(R.id.textProdQtd);
}
}
/** Após pegar o retorno é chamada a função para calcular os totais da venda
* Antes de atribuir o valor do d/a é verificado se já existe um d/a
* Caso exista, ele é retirado dos totais.
* **/
public static void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != 0) {
for (int x = 0; x< AppFunctions.selectedListObj.size(); x++){
Object ab[] = AppFunctions.selectedListObj.get(x);
// if (prodIdOffline.equals(ab[3])) {
String pv = (String) ab[1];
String qt = (String) ab[4];
String da = (String) ab[5];
if ((da != null) && (Double.parseDouble(da) != 0)){
AppFunctions.CalcTotal(Double.parseDouble(pv),Double.parseDouble(qt),Double.parseDouble(da),"DA-");
}
ab[5] = Double.toString(AppFunctions.DESC_ACR);
da = (String) ab[5];
if (da == null)
da = "0";
AppFunctions.CalcTotal(Double.parseDouble(pv),Double.parseDouble(qt),Double.parseDouble(da),"DA");
// }
}
ProductFragment PF = (ProductFragment) ProductFragment.RefreshSalesFragment;
PF.refreshFragment();
}
}
@Override
public ProductItemAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View v = LayoutInflater.from(mContext).inflate(R.layout.product_grid_itens,parent,false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position){
try {
Object selectedObj[] = mDataSet.get(position);
String prodDesc = (String) selectedObj[0];
String prodPrice = (String) selectedObj[1];
final String prodidOffline = (String) selectedObj[3];
String prodQtd = (String) selectedObj[4];
String prodDescAcr = (String) selectedObj[5];
double vQtd = Double.valueOf(prodQtd);
double vDescAcr = 0;
if (prodDescAcr != null)
vDescAcr = Double.valueOf(prodDescAcr);
holder.textProdDesc.setText(prodDesc);
holder.textProdPrice.setText(prodPrice);
holder.textProdQtd.setText(String.format("%.3f", vQtd));
if (vDescAcr < 0){
holder.textProdDescAcr.setTextColor(mContext.getResources().getColor(R.color.colorRed));
holder.textProdDescAcr.setText(String.format("%.3f", vDescAcr));
} else if (vDescAcr > 0){
holder.textProdDescAcr.setTextColor(mContext.getResources().getColor(R.color.colorGreen));
holder.textProdDescAcr.setText(String.format("%.3f", vDescAcr));
}
holder.mCardView.setTag(prodidOffline);
prodSwipedelete_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// mDataSet.remove(holder.getAdapterPosition());
}
});
front_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String displayText = "" + prodidOffline + " clicked";
Log.e("RecyclerAdapter", displayText);
}
});
btnEditProd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
FragmentTransaction ft = ((FragmentActivity)view.getContext()).getSupportFragmentManager().beginTransaction();
ProductEditFragment productEditFragment= new ProductEditFragment();
productEditFragment.show(ft, "dialog");
} catch (Exception e){
Log.e("ProductEditFragment error","error -> "+e.getMessage());
}
}
});
} catch (Exception e) {
Log.e(" Erro ",e.getMessage());
}
}
public void saveStates(Bundle outState) {
viewBinderHelper.saveStates(outState);
}
public void restoreStates(Bundle inState) {
viewBinderHelper.restoreStates(inState);
}
@Override
public int getItemCount(){
return mDataSet.size();
}
}
See the front_layout onclicklistener, it will always pass the idoffline of the button I clicked, and as this is the tag that of the button (in case a cardview), and is the same product id, I can do whatever it takes, edit price, quantity etc.
In other words, the best approach is even using a recicle
Because you don’t use
RecyclerView
? then create the layout, put your list in theadapter
, when the user interacts you change the variable of the model that stores the quantity and then gives anotifyItemChanged(position)
– Eduardo Dornel
Behold
RecyclerView
, as @Eduardodornel quoted. Inside theViewHolder
ofRecyclerView
you implement the product increment and decrement logic and send to theFragment
via Eventbus or Padrão Communicator– Ivan Silva
I’ve been researching about
RecyclerView
, but at least in the tutorials I saw she is instantiated inonCreate
, passing the list right at the assembly, which is not my case.– Dev_ps
In my case initially is inflated a fragment only with
EditText
and aButton
, which the user enters the name of a product, the app sends a request to the server which returns a JSON with the corresponding products, with that I Gero theList
, and process them inFragment
.– Dev_ps
I can do the
RecyclerView
be loaded after the screen has already been mounted? (An observation, I’m new in development for android, I know only the basics of Java, but I realized that it is very different from desktop and Web)– Dev_ps