I have created a compound control with the following:
Java
public class QuantityBox extends LinearLayout
{
private TextView partNmbr;
private Button decrease;
private Button increase;
private EditText quantity;
private int qty;
public QuantityBox(Context context)
{
super(context);
// load views
loadViews();
}
/**
* This constructor is necessary in order to use this compound
* control in an XML layout.
* #param context Application context
* #param attrs
*/
public QuantityBox(Context context, AttributeSet attrs)
{
super(context, attrs);
// inflate the view we created
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.quantity_box, this);
// load views
loadViews();
}
/**
* Load the views created from the constructor
*/
private void loadViews()
{
this.qty = 1;
partNmbr = (TextView) findViewById(R.id.tvPartNmbr);
decrease = (Button) findViewById(R.id.btnDecrease);
increase = (Button) findViewById(R.id.btnIncrease);
quantity = (EditText) findViewById(R.id.etQty);
// set initial text
quantity.setText(this.qty);
decrease.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
// decrease quantity
qty--;
// update view
quantity.setText(qty);
}
});
increase.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
// increase quantity
qty++;
// update view
quantity.setText(qty);
}
});
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvPartNmbr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
/>
<Button
android:id="#+id/btnDecrease"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="-"
/>
<EditText
android:id="#+id/etQty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
/>
<Button
android:id="#+id/btnIncrease"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="+"
/>
</LinearLayout>
And I trying to create it here, programmatic-ally:
public class CustomHeaderActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_title_bar);
QuantityBox qb = new QuantityBox(this);
}
}
Why isn't this working? Am I missing a step? (NullPointerException is thrown.)
The widgets will not be there by the time you call loadViews(). Wait for that until onFinishInflate().
You never inflate your view in the constructor that only takes the Context argument, meaning quantity.setText(...); will throw a NPE because quantity wasn't found in findViewById(...);
Related
I am working on android studio. I am using fragments to make the app workflow. The app is basically for order taking. One customer can have more than one order. So for it, I have used RecyclerView. Below is my GUI
What do I want to do?
I want to update my Total Qty and Order Value in such a way that whenever the user enters the quantity both edittexts should be updated. For example, in the above image, I searched for one product, its rate is 287.30 and when I entered the quantity 5 then Total Qty: 5 and Order Value: 287.30. After that, I select another product and enter its quantity 8 then both edit text should be updated like Total Qty: 13 and Order Value: 509.15, and when I remove any product then it should subtract the total quantity and order value.
The Total Qty: and Order Value: is in my main fragment. Below is my code
Fragment Layout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/products"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:focusable="true" />
</LinearLayout>
<LinearLayout
android:id="#+id/product_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10sp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_product">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total Qty:" />
<EditText
android:id="#+id/total_qty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center_horizontal"
android:hint=""
android:inputType="number" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Order Value :" />
<EditText
android:id="#+id/order_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="center_horizontal"
android:hint=""
android:inputType="none" />
</LinearLayout>
</LinearLayout>
Fragment Code
// created getter setters
public EditText totalQty,totalOrder;
public EditText getTotalQty(){
return totalQty;
}
public void setTotalQty(EditText et){
this.totalQty = et;
}
public EditText getTotalOrder(){return totalOrder;}
public void setTotalOrder(EditText ett){this.totalOrder=ett;}
addProduct.setOnClickListener(v -> {
mProducts.add(new ProductDetail());
mProductsAdapter.setProducts(mProducts);
productsRecyclerView.smoothScrollToPosition(mProducts.size() - 1);
});
Product Layout
<AutoCompleteTextView
android:id="#+id/tv_product"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10sp"
android:gravity="start"
android:hint="Enter Product"
android:inputType="text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/product_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10sp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_product">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:orientation="vertical">
<EditText
android:id="#+id/prod_qty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="left"
android:hint="Enter Quantity"
android:inputType="number" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:orientation="vertical">
<EditText
android:id="#+id/prod_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="left"
android:hint="Prod Price"
android:inputType="numberDecimal" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:orientation="vertical">
<EditText
android:id="#+id/prod_specs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="left"
android:hint="Prod Specs"
android:inputType="none" />
</LinearLayout>
</LinearLayout>
<Button
android:id="#+id/btn_rmv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:text="Remove Product"
android:textColor="#color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/product_infos" />
Product Adapter
View productView = inflater.inflate(R.layout.product_layout, parent, false);
ProductViewHolder viewHolder = new ProductViewHolder(productView);
viewHolder.tvProduct.setAdapter(prodAdapter);
viewHolder.tvProduct.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
#Override
public void afterTextChanged(Editable s) {
mProductManager = new ProductManager(context);
int position = viewHolder.getAdapterPosition();
if (position != -1) {
ProductDetail productDetail = mProductManager.getProductByPrdName(s.toString());
mProducts.get(position).setProductNameFull(s.toString());
viewHolder.price.setText(productDetail.getPrice());
viewHolder.spec.setText(productDetail.getProductSpec());
viewHolder.pgrp.setText(productDetail.getProductGroup());
viewHolder.ccode.setText(productDetail.getCompanyCode());
viewHolder.cname.setText(productDetail.getCompanyName());
viewHolder.pcode.setText(productDetail.getProductCode());
}
}
});
viewHolder.quantity.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
int position = viewHolder.getAdapterPosition();
if (position != -1) {
Integer val = null;
try {
val = Integer.valueOf(s.toString());
} catch (Exception e) {
}
mProducts.get(position).setQuantity(val);
}
}
});
viewHolder.removeBtn.setOnClickListener(v -> {
int position = viewHolder.getAdapterPosition();
if (position != -1) {
mProducts.remove(position);
notifyItemRemoved(position);
}
});
return viewHolder;
Update 1
Below is my Fragment Class
public class SurveyFormFragment extends Fragment {
.
.
.
.
private final LiveData<Integer> mQuantity = new MutableLiveData<>(0);
private final LiveData<Integer> mOrderValue = new MutableLiveData<>(0);
private ViewModel mViewModel;
private FragmentBinding mBinding;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d("myfragment", "onCreateView");
getActivity().setTitle(getString(R.string.title_new_survey));
mContext = getActivity();
if (view == null) {
view = inflater.inflate(R.layout.new_survey_form_layout, container, false);
mLinearLayout = view.findViewById(R.id.ll_prod);
this.initElements(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
this.initListeners(getActivity());
}
Bundle arguments = getArguments();
if (arguments != null && arguments.containsKey("booking_id")) {
isNewSurvey = false;
initSurveyData(arguments.getString("booking_id"));
this.updatingSurveyId = arguments.getString("booking_id");
}
}
Log.d("package", getActivity().getPackageName());
Log.d(TAG, Common.getCarrierName(getActivity()));
return view;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d("myfragment", "onActivityCreated");
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
Log.d("myfragment", "onCreate");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("myfragment", "onDestroy");
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
//save now
savedInstanceState.putString("faisal_qayyum", consumerNameEditText.getText().toString());
super.onSaveInstanceState(savedInstanceState);
Log.d("myfragment", "onSaveInstanceState saving " + consumerNameEditText.getText().toString());
}
#Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
//restore now
Log.d("myfragment", "onViewStateRestored");
}
.
.
.
.
}
Error
How can I add and then update the values?
Any help would be highly appreciated.
I will disappoint you by not sharing code. I will share you a simple graphic of what you need to do.
[Fragment]: displays your list of orders. When an event is triggered (user tapped something or changed something), forwards this event to a ViewModel. Also Observes for the ViewModel data state.
[ViewModel]: exposes a series of functions to listen for user events (e.g. the user tapped this order, or the user changed the quantity of this order to NN, etc.). Also offers a LiveData (or Flow) with the State and Data your Fragment needs. Maybe even talks to the repository where this data originates from (where you save your Orders in your persistent or backend).
Interactions:
When the UI modified something, you tell the viewModel: "This data changed, the order X, now has a quantity of Y".
The ViewModel will process this, update the State of the screen, and send the new data via your Livedata/Flow that the Fragment observes.
When the Fragment receives this new data, it will update the UI accordingly, as that's its most important job.
This whole thing has been greatly documented in the official Android recommended architecture guides. I suggest you start from there instead of trying to fight the framework and making your life more complicated.
implement interface between adapter and fragment like this (it is just sodu to tell how you have to implement things also you have to check it out how to implement interfaces
===============================================================
public frgment extends Fragment implements GetValueInterface{
in onCreate function{
int totalquantity;
call this after adapter initialization
adapter.registergetValueInterface(this)
}
#Override Void setQuantity(Int _gotquantity){
_gotquantity+=_gotquantity;
totalquantityedittext.setText(_gotquantity,TextView.BufferType.EDITABLE)
}
}
and in adapter class
Adapter class
{
public GetValueInterface instance;
function registergetValueInterface(GetValueInterface obj){
instance=obj;
}
//and in quantity edittext text watcher
call instance.setQuantity(quanity)
}
like this you can minus the quantity as well on removal of item
Actually it's releated with Interactions like LiveData.
But rather than write a looot of code, simply I'm passing runnable to childs for call it when somethink changed :)
For example:
class Root{
...
public void addItem(){
ItemController cont = new ItemController(() -> updateSums());
...
}
public void updateSums(){
//TODO
}
}
class ItemController{
Runnable updater;
public ItemController(Runnable updater){
this.updater = updater;
}
public void onSomethingChanged(){
updater.run();
}
}
You should work with LiveData and DataBinding
In order to do so you activate it in your build.gradle file:
android {
...
buildFeatures {
dataBinding true
}
}
Then add the following code.
Add a ViewModel class:
public class ViewModel extends AndroidViewModel
{
private final MediatorLiveData<Integer> mTotalQuantity = new MediatorLiveData<>();
private final MediatorLiveData<Integer> mTotalOrder = new MediatorLiveData<>();
private final List<LiveData<Integer>> mOrders = new ArrayList<>();
private final List<LiveData<Integer>> mQuantities = new ArrayList<>();
public ViewModel(#NonNull Application application)
{
super(application);
mTotalOrder.setValue(0);
mTotalQuantity.setValue(0);
}
public LiveData<Integer> getTotal()
{
return mTotalOrder;
}
public LiveData<Integer> getQuantity()
{
return mTotalQuantity;
}
public void attachQuantity(LiveData<Integer> quantity)
{
mQuantities.add(quantity);
mTotalQuantity.addSource(quantity, (q) -> calculateQuantities());
}
public void detachQuantity(LiveData<Integer> quantity)
{
mQuantities.remove(quantity);
mTotalQuantity.removeSource(quantity);
calculateQuantities();
}
private void calculateQuantities()
{
int total = 0;
for (LiveData<Integer> quantity : mQuantities)
{
Integer value = quantity.getValue();
if (value != null)
{
total += value;
}
}
mTotalQuantity.setValue(total);
}
public void attachTotal(LiveData<Integer> total)
{
mOrders.add(total);
mTotalOrder.addSource(total, (q) -> calculateOrders());
}
public void detachTotal(LiveData<Integer> total)
{
mOrders.remove(total);
mTotalOrder.removeSource(total);
calculateOrders();
}
private void calculateOrders()
{
int total = 0;
for (LiveData<Integer> order : mOrders)
{
Integer value = order.getValue();
if (value != null)
{
total += value;
}
}
mTotalOrder.setValue(total);
}
}
In your fragment class add the following:
private LiveData<Integer> mQuantity = new MutableLiveData<>(0);
private LiveData<Integer> mOrderValue = new MutableLiveData<>(0);
private ViewModel mViewModel;
private FragmentBinding mBinding;
#Override
public void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mViewModel = new ViewModelProvider(requireActivity()).get(ViewModel.class);
mViewModel.attachQuantity(mQuantity);
mViewModel.attachTotal(mOrderValue);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
mBinding = DataBindingUtil.setContentView(this, R.layout.fragment);
mBinding.quantity = mQuantity;
mBinding.order_value = mOrderValue;
}
#Override
public void onDestroy()
{
super.onDestroy();
mViewModel.detachQuantity(mQuantity);
mViewModel.detachTotal(mOrderValue);
}
Add this to your product layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="quantity"
type="android.arch.lifecycle.MutableLiveData<Integer>" />
<variable
name="order_value"
type="android.arch.lifecycle.MutableLiveData<Integer>" />
</data>
...
<EditText
android:id="#+id/prod_qty"
// This does the magic
android:text="#{quantity}" />
...
<EditText
android:id="#+id/prod_price"
// And this of course...
android:text="#{order_value}" />
...
</layout>
And this to your fragment layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewmodel"
type="yourpackage.ViewModel" />
</data>
...
<EditText
android:id="#+id/total_qty"
// This does the magic
android:text="#{viewmodel.quantity}" />
...
<EditText
android:id="#+id/order_value"
// And this of course..
android:text="#{viewmodel.total}" />
...
</layout>
Note that in both classes you need to get the viewmodel from the activity, not from the fragment itself, so you share the same viewmodel for both classes:
ViewModelProvider(requireActivity()).get(ViewModel.class);
If you only get values of LiveData objects from within the UI Thread (which is the case in my code, as onChange of LiveData and binding updates are always called from the UI thread), you do not need to synchronize the lists in the ViewModel. Otherwise you need to make the whole story thread safe.
It is easy to understand that you want to take action when changing the value in a text field. So the first thing is to add a TextChangeListener or TextWatcher. Then, you have to work on the received text value to update the rest of the dependencies: Your product list or whatever it is.
Just a few basic things you need to take care of:
If you are working with fragment communication, propagate your changes by reloading in onResume of the fragment or activity. Or you can use EventBus or any other suitable mechanism.
Be sure to notify the adapter once you have changed the underlying data. I see a call to "notify**" after your code mProducts.get(position).setQuantity(val); is missing in your Product adapter. When modifying the underlying data, it is necessary to notify the adapter using "notify**" calls to update the recycler view.
The MutableLiveData error you posted above can be cleared with MutableLiveData declaration such as private final MutableLiveData mutableData = new MutableLiveData(0) in your case. You can have a function to just return LiveData as LiveData getData() { return mutableData; }
I have been trying to get this to work without success for about 10 hours now, I have looked all over stack overflow. I am trying to get a simple dialog box to appear and handle some simple input.
It has a TextView as a title, EditText as a input field, and two button continue with the operation or cancel.
For some reason, no matter what I do, I cannot seem to be able to reference ANY view inside my shopping_dialogue xml layout. It gives me this error:
java.lang.NullPointerException: Attempt to invoke virtual method
'void android.widget.TextView.setText(java.lang.CharSequence)' on a
null object reference
I have tried to add an onClick event to the button to see if that works, when I try to reference the button inside the onClick method it gives me the same error. I am using a fragment to do this.
shopping_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/shoppingDialogTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Edit Shopping List Name" />
<EditText
android:id="#+id/shoppingDialogEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="30"
android:inputType="textPersonName"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="#+id/shoppingDialogOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
<Button
android:id="#+id/shoppingDialogCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="k"
android:text="Button" />
</LinearLayout>
shopping_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
card_view:cardCornerRadius="4dp"
android:id="#+id/shoppingList_card_view"
android:layout_margin="10dp"
android:layout_height="200dp">
<LinearLayout
android:id="#+id/shoppingListParent"
android:layout_gravity="center"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_height="match_parent">
<TextView
android:id="#+id/shoppingName"
android:layout_width="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:textColor="#FFF"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/shoppingDate"
android:layout_width="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:textColor="#FFF"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
fragment_shopping_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/shoppingList_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
ShopingAdapter.java
public class ShoppingAdapter extends RecyclerView.Adapter<ShoppingAdapter.ShoppingViewHolder> {
private List<ShoppingData> shoppingList;
private Context context;
public ShoppingAdapter(List<ShoppingData> shoppingList, Context context){
this.shoppingList = shoppingList;
this.context = context;
}
#NonNull
#Override
public ShoppingViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i){
View itemView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.shopping_list_row, viewGroup, false);
return new ShoppingViewHolder(itemView);
}
#Override
public void onBindViewHolder(ShoppingViewHolder viewHolder, int i){
ShoppingData data = shoppingList.get(i);
Random k = new Random();
int color = Color.argb(255,k.nextInt(255),k.nextInt(255),k.nextInt(255));
viewHolder.parent.setBackgroundColor(color);
viewHolder.shoppingName.setText(data.getName());
viewHolder.shoppingDate.setText(data.getDate());
viewHolder.shoppingName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder1 = new AlertDialog.Builder(v.getContext());
builder1.setCancelable(true);
builder1.setView(R.layout.shopping_dialog);
AlertDialog alert = builder1.create();
/*
EditText text = v.findViewById(R.id.shoppingDialogEditText);
text.setText("Some Text");
This causes a null object reference
*/
alert.show();
}
});
}
#Override
public int getItemCount(){return shoppingList.size();}
public class ShoppingViewHolder extends RecyclerView.ViewHolder{
private TextView shoppingName, shoppingDate;
private LinearLayout parent;
public ShoppingViewHolder(View itemView){
super(itemView);
parent = itemView.findViewById(R.id.shoppingListParent);
shoppingName = itemView.findViewById(R.id.shoppingName);
shoppingDate = itemView.findViewById(R.id.shoppingDate);
}
}
}
ShoppingFragment.java
public class ShoppingFragment extends Fragment {
private RecyclerView recyclerView;
private ShoppingAdapter shoppingAdapter;
private List<ShoppingData> shoppingList = new ArrayList<>();
#NonNull
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState){
shoppingList.add(new ShoppingData("k","12/12/12"));
shoppingList.add(new ShoppingData("k","12/12/12"));
shoppingList.add(new ShoppingData("k","12/12/12"));
shoppingList.add(new ShoppingData("k","12/12/12"));
shoppingList.add(new ShoppingData("k","12/12/12"));
shoppingList.add(new ShoppingData("k","12/12/12"));
View rootView = inflater.inflate(R.layout.fragment_shopping_list, container, false);
recyclerView = rootView.findViewById(R.id.shoppingList_recycler_view);
shoppingAdapter = new ShoppingAdapter(shoppingList, getActivity());
RecyclerView.LayoutManager manager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(shoppingAdapter);
return rootView;
}
public void k(View view){ //the click listern that causes a null object reference when referencing the button
Button button = view.findViewById(R.id.shoppingDialogOk);
button.setText("k");
}
}
ShoppingData.java
package com.uhcl.recipe5nd.helperClasses;
public class ShoppingData {
private String name;
private String date;
public ShoppingData(String name, String date){
this.name = name;
this.date = date;
}
public String getDate(){
return this.date;
}
public String getName(){
return this.name;
}
}
Everything works fine until I try to reference anything inside shopping_dialog.xml.
If you look at my shopping adapter class, what I am trying to do is to add an onClick listener to the "shoppigName" text view inside my onBindViewHolder method. This works, but when I try to reference the shoppingDialogEditText, it causes the app the crash and give me that error.
Like I mentioned I also tried adding a click event method k to a button inside shopping_dialog.xml, and implemented it inside my fragment class to see if that would work, but it still causes the same error.
viewHolder.shoppingName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View dailogView = LayoutInflater.from(mContext).inflate(R.layout.shopping_dialog, null);
AlertDialog.Builder builder1 = new AlertDialog.Builder(v.getContext());
builder1.setCancelable(true);
builder1.setView(dailogView);
AlertDialog alert = builder1.create();
EditText text = dailogView.findViewById(R.id.shoppingDialogEditText);
text.setText("Some Text");
alert.show();
}
});
The view your using to the find the edittext is not the view of that dialog box, therefore it's throwing null pointer.
You are using a wrong view to find the editText. It is not the view of dialog box. It is the view of the item which is being clicked rather than dialog box.
Use this
viewHolder.shoppingName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View dailogView =
LayoutInflater.from(mContext).inflate(R.layout.shopping_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setCancelable(true);
builder.setView(dailogView);
AlertDialog alert = builder.create();
EditText text = dailogView.findViewById(R.id.shoppingDialogEditText);
text.setText("Shopping Dialog Text");
alert.show();
}
});
}
I am in the making of a shopping list using a ListView with custom items with the posibility of increasing the amount of that item and also decreasing the amount.
At the moment, I get the right amount of items when I load them in to the shopping list, as can seen in the image below:
the image of the ListView and problem
But the problem occurs when I am trying to increase/decrese the amount of each item by clicking the buttons, only the last item in the ListView gets updated by the clicks.
The reason for this is because i am re-declaring the TextView for each item, and the others (probably?) doesn't get stored anywhere. So i read about "setTag()" and "getTag()" and tried to implement but this didn't work either (maybe beacuse i did it wrong).
I am using a custom class called "Item" which stores each item and the amount of that item.
Otherwise, this is the custom adapter and the .xml
public class ShoppingListAdapter extends ArrayAdapter<Item> {
int amount;
TextView amountText;
private Context mContext;
int mResource;
public ShoppingListAdapter(#NonNull Context context, int resource, #NonNull ArrayList<Item> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
//get the item information
String name = getItem(position).getName();
String brand = getItem(position).getBrand();
int id = getItem(position).getId();
String img = getItem(position).getImg();
amount = getItem(position).getAmount();
//all info
Item item = new Item(name,id,brand,img);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource,parent,false);
TextView tVName = (TextView) convertView.findViewById(R.id.textView2);
ImageView imgV = (ImageView) convertView.findViewById(R.id.imageView);
TextView tVId = (TextView) convertView.findViewById(R.id.textView3);
amountText = (TextView) convertView.findViewById( R.id.amountItem );
tVName.setText(name);
amountText.setText( String.valueOf( amount ) );
amountText.setTag(position);
Picasso.with(mContext).load(img).into(imgV); // tVBrand.setText(brand);
//tVId.setText(id);
//Buttons
Button addButton =(Button) convertView.findViewById(R.id.addValue);
Button subButton =(Button) convertView.findViewById(R.id.subValue);
addButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
getItem(position).incrementAmount();
//This gives the right position and the amount for all items
Log.d("ifIncreased", " " + getItem(position).getAmount());
Log.d("ifIncreased", position + "" );
TextView newText = (TextView) amountText.getTag(position);
newText.setText( String.valueOf( getItem(position).getAmount()));
}
} );
subButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
if(getItem(position).getAmount() == 1)
{
//TODO remove from list;
}
else{
getItem(position).decrementAmount();
Log.d("ifIncreased", position + "" );
amountText.setText( String.valueOf( getItem(position).getAmount()) );
}
}
} );
return convertView;
}
and the XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="100">
<ImageView
android:id="#+id/imageView"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_weight="33.3"
app:srcCompat="#mipmap/ic_launcher" />
<LinearLayout
android:layout_width="212dp"
android:layout_height="60dp"
android:layout_weight="33.3"
android:orientation="vertical">
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_below="#+id/textView2"
android:gravity=""
android:paddingLeft="10dp"
android:text="TextView3" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity=""
android:paddingLeft="10dp"
android:text="TextView2" />
</LinearLayout>
<LinearLayout
android:layout_width="112dp"
android:layout_height="60dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/amountItem"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="1"
android:textStyle="bold" />
<Button
android:id="#+id/addValue"
android:layout_width="40dp"
android:layout_height="33dp"
android:layout_gravity="center"
android:text="+"
android:textAlignment="center"
android:textSize="12sp" />
<Button
android:id="#+id/subValue"
android:layout_width="40dp"
android:layout_height="33dp"
android:layout_gravity="center"
android:text="–"
android:textAlignment="center"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
So- since I am having the right values in the onClick functions, my question is, how can I change each TextView (the amount of that item) from the items in the full list?
Try this to update single value into adapter.. make public method and that method called into fragment or activity when you updated any value and refresh adapter.
/**
* this method used to update list item when broad cast received.
* #param percentage
* #param position
*/
public void updateProgress(double percentage, final int position) {
feedBackVoList.get(position).setPercentage(percentage);
notifyItemChanged(position);
}
after that updated value set into textview when you called notifyItemChanged(position) reset again that row or refresh that row.
I have a problem ,I create recyclerview and its work fine at the first search data from api , it display fine but when I try to search with new data ( second time ) it is not display anything i try to test and debug every every thing work fine and new data enter to adapter and get the result fine and set adapter to recyclerview but it is not showing any thing
I try several method like use only one adapter and change it's list of Date and use notifyDataSetChange but not work still only show at the first time
Below activity is use to search get date ( use in searching data )
fromDate to toDate
DeliveryReportActivity.java
public class DeliveryReportActivity extends AppCompatActivity
implements DateDialogFromFragment.SelectDateFromInterface,
DateDialogToFragment.SelectDateToInterface {
Button btn_from;
Button btn_to;
EditText et_fromDate;
EditText et_toDate;
Button search_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_delivery_report);
btn_from=(Button)findViewById(R.id.btn_fromDate);
btn_to=(Button)findViewById(R.id.btn_toDate);
et_fromDate = (EditText) findViewById(R.id.from_date);
et_toDate = (EditText) findViewById(R.id.to_date);
search_btn=(Button)findViewById(R.id.search_delivery_report_btn);
et_fromDate.setText(new SimpleDateFormat("yyyy-MM-dd").format(new
Date()));
et_toDate.setText(new SimpleDateFormat("yyyy-MM-dd").format(new
Date()));
btn_from.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DateDialogFromFragment dateDialogFragment = new
DateDialogFromFragment();
android.app.FragmentTransaction ft =
getFragmentManager().beginTransaction();
dateDialogFragment.show(ft, "DatePicker");
}
});
btn_to.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DateDialogToFragment dateDialogFragment = new
DateDialogToFragment();
android.app.FragmentTransaction ft =
getFragmentManager().beginTransaction();
dateDialogFragment.show(ft, "DatePicker");
}
});
search_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle=new Bundle();
bundle.putString("from",et_fromDate.getText().toString()+ "
00:00:00");
bundle.putString("to",et_toDate.getText().toString()+" 23:59:59");
Intent intent =new
Intent(DeliveryReportActivity.this,DeliveryReportListActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
});
}
#Override
public void onGetSelectFromDate(String fromDate) {
et_fromDate.setText(fromDate);
}
#Override
public void onGetSelectToDate(String toDate) {
et_toDate.setText(toDate);
}
}
and it's view activity_delivery_report.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:orientation="vertical"
tools:context="com.exatech.groupsmsandroid.activity.
deliveryReport.DeliveryReportActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/btn_fromDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/From"
android:textSize="18dp" />
<EditText
android:id="#+id/from_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2017-12-26" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:orientation="horizontal">
<Button
android:id="#+id/btn_toDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/to" />
<EditText
android:id="#+id/to_date"
android:text="2017-12-26"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_centerInParent="true"
android:gravity="center"
android:layout_marginTop="20dp"
android:id="#+id/search_delivery_report_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:text="#android:string/search_go" />
</RelativeLayout>
</LinearLayout>
after I press the search button it's start new activity that show my recylerview the new activity is
DeliveryReportListActivity .java
public class DeliveryReportListActivity extends AppCompatActivity implements
DeliveryReportService.DeliveryReportServiceInterface {
private static final String TAG = "GSMS";
private Bundle bundle;
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_delivery_report_list);
recyclerView = (RecyclerView) findViewById(R.id.delivery_report_rv);
}
#Override
protected void onResume() {
super.onResume();
bundle = getIntent().getExtras();
String from = bundle.getString("from");
String to = bundle.getString("to");
DeliveryReportService.getInstance(this).
getDeliveryReportFromDateToDate(from, to);// Call api get deliver
}
#Override
public void onGetDeliveryReport(Response<List<DeliveryReportResource>>
listResponse) {// response
Log.i(TAG, "onGetDeliveryReport: listResponse.body():" +
listResponse.body());
DeliveryReportAdapter deliveryReportAdapter = new
DeliveryReportAdapter(DeliveryReportListActivity.this, listResponse.body());
recyclerView.setAdapter(deliveryReportAdapter);
deliveryReportAdapter.notifyDataSetChanged();
Toast.makeText(DeliveryReportListActivity.this, "Delivery Report Success
", Toast.LENGTH_SHORT).show();
}
#Override
public void onDeliveryConnectionFailed() {
Toast.makeText(DeliveryReportListActivity.this, "Connect Error ",
Toast.LENGTH_SHORT).show();
}
}
and it's view activity_delivery_report_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.exatech.groupsmsandroid.activity.deliveryReport.
DeliveryReportListActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:text="#string/text"
android:layout_weight="3"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_weight="4"
android:text="#string/phone_no"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_weight="4"
android:text="#string/status"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/delivery_report_rv"
android:layout_width="match_parent"
app:layoutManager="LinearLayoutManager"
android:layout_height="match_parent"
tools:listitem="#layout/delivery_report_list_content"/>
</LinearLayout>
Below is Myadapter Class
**DeliveryReportAdapter.java**
public class DeliveryReportAdapter extends
RecyclerView.Adapter<DeliveryReportAdapter.ViewHolder> {
List<DeliveryReportResource> listDeliveryReport;
Context context;
public DeliveryReportAdapter(Context context, List<DeliveryReportResource>
listDeliveryReport) {
this.listDeliveryReport = listDeliveryReport;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(parent.getContext()).
inflate(R.layout.delivery_report_list_content, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.item = listDeliveryReport.get(position);
holder.text.setText(holder.item.getText());
CustomAdapterFroDeliveryReport adapterFroDeliveryReport = new
CustomAdapterFroDeliveryReport(context, R.layout.two_text_contect,
listDeliveryReport.get(position).getSmsSubscribedRecipientsResourceList());
holder.phoneNoAndStatus.setAdapter(adapterFroDeliveryReport);
holder.view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "click message no=" +
holder.item.getText(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return listDeliveryReport.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
View view;
TextView text;
ListView phoneNoAndStatus;
DeliveryReportResource item;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
text = (TextView) itemView.findViewById(R.id.message_tv);
phoneNoAndStatus = (ListView)
itemView.findViewById(R.id.phoneNo_and_status_lv);
}
}
}
Try to create an adapter once and then update items
Add next code to your adapter class
ArrayList<DeliveryReportResource> listDeliveryReport = new ArrayList<DeliveryReportResource>();
public DeliveryReportAdapter(Context context) {
this.context = context;
}
public void updateItems(List<DeliveryReportResource> list) {
listDeliveryReport.clear();
listDeliveryReport.addAll(list);
notifyDataSetChanged();
}
Then create adapter once in onCreate() and place it as global variable
And now you should call adapter.updateItems(...) every time you want to change data
I have a custom control which is supposed to work like the Segmenttab controller in iOS.
It has 3 textviews and the layout is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/groupofthree"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/background"
android:orientation="horizontal" >
<TextView
android:id="#+id/tv_1"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#color/black"
android:gravity="center"
android:text="Retiree"
android:textColor="#color/whitetext"
android:textSize="15dp"
android:textStyle="normal" />
<TextView
android:id="#+id/tv_2"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#color/lightGrey"
android:gravity="center"
android:padding="3dp"
android:text="Under18/fulltime"
android:textColor="#color/whitetext"
android:textSize="15dp"
android:textStyle="normal" />
<TextView
android:id="#+id/tv_3"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#color/black"
android:gravity="center"
android:text="Others"
android:textColor="#color/whitetext"
android:textSize="15dp"
android:textStyle="normal" />
</LinearLayout>
The control looks like this:
public class SegmentedRadioGroup extends View{
private Context m_Context;
public TextView tv1;
public TextView tv2;
public TextView tv3;
int selectedIndex = 0;
public SegmentedRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
m_Context = context;
}
public SegmentedRadioGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SegmentedRadioGroup(Context context) {
super(context);
// TODO Auto-generated constructor stub
m_Context = context;
LayoutInflater inflater = (LayoutInflater) m_Context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.threeradiobutton, null);
v.isInEditMode();
tv1 = (TextView) v.findViewById(R.id.tv_1);
tv2 = (TextView) v.findViewById(R.id.tv_2);
tv3 = (TextView) v.findViewById(R.id.tv_3);
tv1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
selectedIndex = 0;
tv1.setBackgroundColor(R.color.darkgrey);
tv2.setBackgroundColor(R.color.lightGrey);
tv3.setBackgroundColor(R.color.lightGrey);
}
});
tv2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
selectedIndex = 1;
tv1.setBackgroundColor(R.color.lightGrey);
tv2.setBackgroundColor(R.color.darkgrey);
tv3.setBackgroundColor(R.color.lightGrey);
}
});
tv3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
selectedIndex = 2;
tv1.setBackgroundColor(R.color.lightGrey);
tv2.setBackgroundColor(R.color.lightGrey);
tv3.setBackgroundColor(R.color.darkgrey);
}
});
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
}
}
The activity in which i add this custom view to the layout is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/background"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/widget1216"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/appspecific_menubar" >
<TextView
android:id="#+id/widget1222"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/transaction_accounts_topbar"
android:textColor="#color/whitetext"
android:textSize="18sp"
android:textStyle="bold" >
</TextView>
<ImageButton
android:id="#+id/home_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#null"
android:paddingBottom="5dip"
android:paddingLeft="10dip"
android:paddingTop="5dip"
android:src="#drawable/home" >
</ImageButton>
</RelativeLayout>
<LinearLayout
android:id="#+id/testLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />.
</LinearLayout>
And the activity looks like this. I have added the view into the layout using addview.
public class TransactionAccount extends Activity {
LinearLayout selector;
SegmentedRadioGroup sg_test;
LayoutInflater inflater;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.transactionaccount_main);
selector = (LinearLayout)findViewById(R.id.testLayout);
sg_test = new SegmentedRadioGroup(this);
selector.addView(sg_test);
// inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// selector = inflater.inflate(R.id., null);
// sg_test = new SegmentedRadioGroup(this);
// sg_test.tv1.setText("1");
// sg_test.tv2.setText("2");
// sg_test.tv3.setText("3");
// sg_test.tv1.setBackgroundColor(R.color.blacktext);
// sg_test.setVisibility(View.VISIBLE);
//
// Log.d("TransactionAccount", "onCreate++++++" + sg_test.tv1.getText());
// Log.d("TransactionAccount", "onCreate++++++" + sg_test.tv2.getText());
// Log.d("TransactionAccount", "onCreate++++++" + sg_test.tv3.getText());
}
}
But what i see on the screen is a blank screen.. and not the custom control which should show up. Kindly tell me where am i going wrong.
Thanks in advance.
First of all, you can't add child Views to a subclass of View because it doesn't have the addView method. Instead, you should extend ViewGroup or one of its subclasses(like LinearLayout, RelativeLayout etc).
After you do the above thing you can simple add the Views with:
View v = inflater.inflate(R.layout.threeradiobutton, this, true);
to actually add the inflated layout to the custom View.
Right now you don't see something on the screen because there isn't something to see, your custom View is empty.