The recyclerView is used to display a custom ArrayList of products and this view can be switched between different types of products by the user via radio buttons that call swapAdapter. The products are all filtered by diameter via spinner bar selection, and since the user will want to get products of matching diameter, the filter must hold as the adapters swap. All of this is working in the view, however when the user selects an item to add to the cart, the cart will show the wrong item. It will be from the same position however, from the previous adapter. As these adapters switch so does the last adapter. Why are the views refreshing but the data linked to the position is always one and only one step behind?
Here is the RecyclerView
mRecyclerView = findViewById(R.id.inventory_recycler_view);
mLayoutManager = new LinearLayoutManager(this);
aAdapter = new CustomAdapter(aList);
bAdapter = new CustomAdapter(bList);
cAdapter = new CustomAdapter(cList);
dAdapter = new CustomAdapter(dList);
eAdapter = new CustomAdapter(eList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(aAdapter);
and here is the radio group
bButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mRecyclerView.swapAdapter(bAdapter, true);
bAdapter.getFilter().filter(filterDiameterString);
// bAdapter.notifyDataSetChanged();
}
});
cButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mRecyclerView.swapAdapter(cAdapter, true);
cAdapter.getFilter().filter(filterDiameterString);
// cAdapter.notifyDataSetChanged();
}
});
dButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mRecyclerView.swapAdapter(dAdapter, true);
dAdapter.getFilter().filter(filterDiameterString);
// dAdapter.notifyDataSetChanged();
}
});
eButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mRecyclerView.swapAdapter(miscAdapter, true);
eAdapter.getFilter().filter(filterDiameterString);
// eAdapter.notifyDataSetChanged();
}
});
The following has been attempted:
notifyDataSetChange
recyclerview.invalidate
adapter.clear()
I was able to resolve this issue by adding a setter to my arraylist in the custom adapter and then changed the list via the setter then called notify data set change.
Related
I'm developing an application which contains a listview with some article but I have confusion with using of notifyDataSetChanged().
My confusion derived from insert operation because I want add a new item to listview from dialog. The "problem" is on add button click of dialog: I create a new Product item and add to productsList then call notifyDataSetChanged() to refresh listview, but I could not call it because my listview is updated anyway and I not understand if it is correct or not also because if I not use dialog to add, without notify method listview doesn't refresh.
I did some research and all of them use notify method.
Below the code that I use in my Fragment:
productsList = new ArrayList<>();
mAdapter = new products_list_adapter(getActivity(), productsList);
asyncProducts = new GetProductsAsyncTasks(getActivity(), productsList, listViewProducts);
asyncProducts.execute();
final Dialog dialog = new Dialog(getActivity());
btnAggiungiProdotto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.setTitle("Add");
dialog.setContentView(R.layout.input_dialog);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, 1000);
dialog.setCancelable(true);
Button btnConferma = (Button) dialog.findViewById(R.id.btnConferma);
btnConferma.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText txtDescr = (EditText) dialog.findViewById(R.id.edtDescrizione);
EditText txtBarcode = (EditText) dialog.findViewById(R.id.edtBarocode);
Product p = new Product();
p.SetDescription(txtDescr.getText().toString());
p.SetBarCode(txtBarcode.getText().toString());
productsList.add(p);
mAdapter.notifyDataSetChanged();
dialog.dismiss();
}
});
I would know this behaviour is correct or not.
I want to store selected checkbox values in ArrayList. There is five checkbox if I select three then they will store on ArrayList. I used String []ad = new String[5]; is it write on not to store the value of checkbox
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
List<String> mList = new ArrayList<>();
CheckBox android, java, python, php, unity3D;
Button submitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
android = (CheckBox) findViewById(R.id.androidCheckBox);
android.setOnClickListener(this);
java = (CheckBox) findViewById(R.id.javaCheckBox);
java.setOnClickListener(this);
python = (CheckBox) findViewById(R.id.pythonCheckBox);
python.setOnClickListener(this);
php = (CheckBox) findViewById(R.id.phpCheckBox);
php.setOnClickListener(this);
unity3D = (CheckBox) findViewById(R.id.unityCheckBox);
unity3D.setOnClickListener(this);
submitButton = (Button) findViewById(R.id.submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("ArrayList Values*******",mList.toString());
}
});
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.androidCheckBox:
if (android.isChecked()) {
mList.add(String.valueOf(android.getText()));
Log.e("Android*******",mList.toString());
}
break;
case R.id.javaCheckBox:
if (java.isChecked()) {
mList.add(String.valueOf(java.getText()));
Log.e("Java*******",mList.toString());
}
break;
case R.id.phpCheckBox:
if (php.isChecked()) {
mList.add(String.valueOf(php.getText()));
Log.e("PHP*******",mList.toString());
}
break;
case R.id.pythonCheckBox:
if (python.isChecked()){
mList.add(String.valueOf(python.getText()));
Log.e("Python*******",mList.toString());
}
break;
case R.id.unityCheckBox:
if (unity3D.isChecked()){
mList.add(String.valueOf(unity3D.getText()));
Log.e("Unity*******",mList.toString());
}
break;
}
}
}
Just create a List and add values when your click events are fired:
final List<String> mList = new ArrayList<>();
mList.add("Your value");
Note: consider to implement onCheckChangeListener intead of onClickListener to handle your checkbox selection events.
No, it's not quite correct.
I strongly recommend creating the array when the user presses submitButton. Otherwise, if they check some boxes, and either
Rotate the screen, or
Put the app in the background and the Activity gets destroyed by the system (You can simulate this by selecting the "Don't keep Activities" option in Developer Options)
When they see your UI again, it will be correctly re-created - all the boxes the user has checked will still be checked, but your array will be empty! I recommend something like
submitButton = (Button) findViewById(R.id.submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String []ad = new String[5];
if (android.isChecked()) {
ad[0] = (String) android.getText();
}
if (java.isChecked()) {
ad[1] = (String) java.getText();
}
...
}
});
If you care about ad outside the context of submitting the user's choices, the best practice is to save it in the Bundle in public void onSaveInstanceState(Bundle outState) {}
and fetch and set it in your onCreate(Bundle savedInstanceState){}. This way you will not loose data even on orientation change, or on the system destroying your Activity. See this answer for details on how to do that.
I have a BottomSheet "buttomSheet" (in this sheet it is a list view that is GONE) and a normal Button "btnShowListView" (out from the "buttomSheet").
I want that when I click on "btnShowListView" the list view in the bottomSheet will be Visible its work but only after 2 clicks on button "btnShowListView"...
this is my code:
final View bottomSheetView = findViewById(R.id.bottomSheetLayout);
listView = (ListView) bottomSheet.findViewById(R.id.listView);
buttomSheet = BottomSheetBehavior.from(bottomSheetView);
btnShowListView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listView.setVisibility(View.VISIBLE);
bottomSheetView.requestLayout();
bottomSheetView.invalidate();
bottomSheet.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
You can make the listview already visible, there's no need to hide it; you can get te same effect by setting the state of the bottom sheet behavior to HIDDEN.
I tested the code below and it should work also for you.
final View bottomSheetView = findViewById(R.id.bottomSheetLayout);
bottomSheetBehavior= BottomSheetBehavior.from(bottomSheetView);
bottomSheetBehavior.setHideable(true);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
btnShowListView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bottomSheet.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
I targeted the items in an action bar using ShowcaseView, but I can't target elements of a ListView! I tried that and it didn't work:
ShowcaseView sv = new ShowcaseView.Builder(this,true)
.setTarget(new ViewTarget(lv.getChildAt(1).findViewById(R.id.heart)))
// Here is where you supply the id of the action bar item you
// want to display
.setContentTitle("Heart")
.setContentText("Check the venues of your city")
.hideOnTouchOutside()
.build();
Very simple. Take the element in your ViewHolder then place the code for showing the ShowCaseView inside your bindView.
Don't forget to put different a different ID for each element in the list.
So you may try something like this.
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView button;
public ViewHolder(final View itemView) {
super(itemView);
button = (Button) itemView.findViewById(R.id.list_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MaterialShowcaseView.Builder(getActivity())
.setTarget(verifyButton)
.setDismissText("GOT IT")
.setContentText("Your text goes here")
.setDelay(100) // optional but starting animations immediately in onCreate can make them choppy
.singleUse(id + " define an unique id for each item of the list") // provide a unique ID used to ensure it is only shown once
.show();
}
});
}
}
}
To get more information you can check the library here.
I'm attempting to create an onClick listener for each item in my imageCarousel - however I'm unable to create a unique listener for each object in the carousel.
Currently - the listener functions - but it applies to all items in the carousel - and my attempts at finding/using the unique ID for each item has failed.
Current implementation:
for (int i = 0; i < titleResourcesTypedArray.length(); ++i) {
// Create new ImageView
imageItem = new ImageView(this);
// Set the shadow background
imageItem.setBackgroundResource(R.drawable.shadow);
// Set the image view resource
imageItem.setImageResource(titleResourcesTypedArray.getResourceId(
i, -1));
// Set the size of the image view to the previously computed value
imageItem.setLayoutParams(new LinearLayout.LayoutParams(imageWidth,
imageWidth));
//imageItem.setOnClickListener(this);
// Add image to the carousel
mCarouselContainer1.addView(imageItem);
imageItem.setOnClickListener(new View.OnClickListener() {
// create an onClick Listener
#Override
public void onClick(View v) {
// create an onClick Event (Start the Map Download)
Intent intent = new Intent(Home.this, Download.class);
startActivity(intent);
}
});
}
Desired implementation:
I believe I should be using something along the lines of:
imageItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
titleResourcesTypedArray.getResources();
if (v.getId() = 7) {
Intent intent = new Intent(Home.this, Download.class);
startActivity(intent);
...
or perhaps:
imageItem.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
titleResourcesTypedArray.getResources();
if (v.getResources() = 10) {
// Do Stuff
Intent intent = new Intent(Home.this, Download.class);
startActivity(intent);
}
}
}
How might I properly identify the ID of each item in a carousel?
In addition to comparing with ids, there is an additional way to use a 'tag'. You can set a tag on the imageView using the setTag method and then in the onClick method you can compare this tag.
To add a View.OnClickListener on items in a Carousel with MotionLayout is not different to any other scenarios.
Assume a motionlayout.xml as
<androidx.constraintlayout.motion.widget.MotionLayout ...
android:id="#+id/motionLayoutCarousel"
...
<ImageView android:id="#+id/item1" .../>
<ImageView android:id="#+id/item2" .../>
...
<ImageView android:id="#+id/item5" .../>
<androidx.constraintlayout.helper.widget.Carousel
... />
</androidx.constraintlayout.motion.widget.MotionLayout>
then in the Fragment (or Activity) where the motionLayoutCarousel is inflated, simply add code like below. Note: example below uses View Binding, but this is actually irrelevant.
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
MotionlayoutBinding binding = MotionlayoutBinding.inflate(inflater, container, false);
final #IdRes int[] clickableViews = {
R.id.item1, R.id.item2, R.id.item3, R.id.item4, R.id.item5
};
for (#IdRes int v : clickableViews) {
View clickView = binding.motionLayoutCarousel.findViewById(v);
clickView.setOnClickListener(this);
}
}
#Override
public void onClick(View v) {
final #IdRes int id = v.getId();
Integer idx = (Integer) v.getTag();
Log.i(LOGTAG, "onClick 0x" + Integer.toHexString(id) + " idx " + idx);
}
In the Adapter of the Carousel you need to assign the index of a certain item via setTag. Then the onClick(View) will allow you to know, which index into the data was actually clicked.
#Override
public void populate(View view, int index) {
view.setTag(index)
...
}