How to manipulate buttons at runtime on android

Asked

Viewed 430 times

0

I’m creating an app for a restaurant, where I can already list orders and create the interface, example: coca-cola - 0 + I use a for to go through one List, which generates the list of products. MY PROBLEM: As these elements are created at runtime, I found no way to manipulate them, I need that when the button + is clicked a function is fired incrementing the number between the buttons, for this the function must pick the value between the buttons and increment more 1. For the same purpose, something similar by clicking on the minus button.

I did several searches on google and found nothing about it, I can do these features using Js. This code is running inside a Fragment, the List comes from an interaction with the Activity that makes a consumption of a WEB service via JSON.

for(int j=0;j<contador;j++)
        {

            LinearLayout ll = new LinearLayout(getContext());
            ll.setTag("ll"+j);
            ll.setLayoutParams(params);
            ll.setOrientation(LinearLayout.HORIZONTAL);


            TextView product = new TextView(getContext());
            product.setTextSize(15);
            product.setLayoutParams(new LinearLayout.LayoutParams(520, 80));//LinearLayout.LayoutParams.MATCH_PARENT)
            product.setTop(0);
            product.setText(String.valueOf(prods.get(j).getNome()));
            ll.addView(product);

            /*
            TextView price = new TextView(getContext());
            price.setText(String.valueOf(prods.get(j).getCod()));
            ll.addView(price);*/

            Drawable me = getResources().getDrawable(R.drawable.skinbtnmenos);

            Button btn = new Button(getContext());

            btn.setId(j+1);
            btn.setTop(0);
            btn.setBackground(me);

            //btn.setText("Add");
            // set the layoutParams on the button
            btn.setLayoutParams(new LinearLayout.LayoutParams(50, 50));


            TextView qtd = new TextView(getContext());
            qtd.setId(j);
            qtd.setTextSize(15);
            qtd.setLayoutParams(new LinearLayout.LayoutParams(30, LinearLayout.LayoutParams.MATCH_PARENT));//LinearLayout.LayoutParams.MATCH_PARENT)
            qtd.setTop(0);
            qtd.setText("0");


            Drawable ma =getResources().getDrawable(R.drawable.skinbtnmais);
            Button b = new Button(getContext());
            // Give button an ID
            b.setId(-j);
            b.setTop(0);
            b.setBackground(ma);
            // set the layoutParams on the button
            b.setLayoutParams(new LinearLayout.LayoutParams(50, 50));

            final int index = j;
            // Set click listener for button
            btn.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    if (mListener!=null){
                        String id = v.getId()+"";
                        mListener.alterarValor(id);
                    }
                    /*Log.i("TAG", "index :" + index);*/
                    alerta("Valor:" + index);
                    //Toast.makeText(getApplicationContext(),
                    //"Clicked Button Index :" + index,
                    //Toast.LENGTH_LONG).show();

                }
            });

            //Add button to LinearLayout
            ll.addView(btn);
            ll.addView(qtd);
            ll.addView(b);

            //Add button to LinearLayout defined in XML
            parent.addView(ll);
        }
  • Because you don’t use RecyclerView ? then create the layout, put your list in the adapter, when the user interacts you change the variable of the model that stores the quantity and then gives a notifyItemChanged(position)

  • Behold RecyclerView, as @Eduardodornel quoted. Inside the ViewHolder of RecyclerView you implement the product increment and decrement logic and send to the Fragment via Eventbus or Padrão Communicator

  • I’ve been researching about RecyclerView, but at least in the tutorials I saw she is instantiated in onCreate, passing the list right at the assembly, which is not my case.

  • In my case initially is inflated a fragment only with EditText and a Button, 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 the List, and process them in Fragment.

  • 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)

1 answer

0


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

  • I found your example interesting, helped me create the RecyclerView, I’m just not getting to call him on my fragment, the only difference from yours basically, is that I’m not calling him on onCreateView, because at this point I will not have the list of objects, my user will search in a search bar on Fragment and only then will I have the list with the objects, as implement RecyclerView in that case?

  • Good! you can create it in the empty oncreacteview. And then populate it at the necessary time, in your case, in the search. I use this method to create an empty recyclerView and go populating according to user selections.

  • I did it in a way that worked, but he makes that mistake E/RecyclerView: No adapter attached; skipping layout, although this error does not close the application, wanted to fix

  • Take a look at the line where you assign the view to recyclerview and the layoutmanager. Make sure you’re giving the view a findview. Or there in the Adapter, there in the viewholder , checks if the findview is also correct.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.