How to know if a RecyclerView has enough content to scroll? - java

Currently I am using a RecyclerView with a LinearLayout Manager and an EditText as HeaderView for filtering the content of the list.
I would like to hide the EditText if the content of the RecyclerView is smaller than the RecyclerView itself.
Is there any way to "ask" the Recyclerview or the LayoutManager if its content can scroll?
Thank you all.

RecyclerView can't scroll anymore when the item at last position is completely visible.
In condition that would sound as:
mRecyclerView.getLayoutManager().findLastCompletelyVisibleItemPosition() == mRecyclerViewAdapter.getItemCount() - 1;

An answer that also accounts for dynamic screen sizes.
mRecyclerView.getViewTreeObserver().addOnScrollChangedListener(() -> {
if (mRecyclerView.canScrollVertically(1) && //still scrolling
mRecyclerView.computeVerticalScrollRange() >= mRecyclerView.getHeight()) { //Big enough for scrolling
return; //we still scrolling so early out.
}
DoMyFunction();
}

do you mean this:
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.LayoutManager.html#canScrollVertically()
if(recyclerView.getLayoutManager().canScrollVertically()){
// do stuff
} else{
// do other stuff
}

Related

I want to add Edit Text dynamically not more not less than 5 Edit Texts in android java

I need to add 5 Input fields (EditText) dynamically one by one on button click and want to take values from them and store them into database using Room Persistence with MVVM.
Here I'm adding the view dynamically
private void addEditTextView() {
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
}
Any suggestion would be very helpful.
Thank you in advance.
Add view based on child count
private void addEditTextView() {
if (binding.layoutList.getChildCount() <= 5) {
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
}
}
"When I clicked Add button it is adding input field one by one, this code is working but I just want to limit for 5 fields not more not less and take values from them."
If you want to add exactly 5 fields on button click I recommend designing a fragment with the 5 fields in place, then when the button is clicked, inflate the fragment into your parent view. Then code the fragment appropriately with the data you're working with.
Then if you wanted, you could deflate the fragment on button click to clear the view or add some other way to clear the fragment when you want. Much easier than what you're doing currently in my own opinion.
You might as well include a submit button in your fragment assuming this is some kind of form.
You can simply define an integer and increase it every time you add the EditText but you should check if your integer is less than 5 everytime the method is called.
Example
private void addEditTextView() {
int count = 0;
if (count < 5){
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
count++;
}
}

Scrolling recyclerview using buttons right and left

I want to use right and left buttons to scroll items with like 10 items
I tried to use scrollBy but it did not work
Here is my Layout Image.
I want to be able to scroll right and left
You can use for Next button:
mRecyclerView.getLayoutManager().scrollToPosition(linearLayoutManager.findLastVisibleItemPosition() + 1);
And for Previous Button:
mRecyclerView.getLayoutManager().scrollToPosition(linearLayoutManager.findFirstVisibleItemPosition() - 1);
Have look this
You can have a variable that tracks the current displayed position of the RecyclerView, named it "currentPosition" in below snippets
Then increment it if you want to navigate to the next item as follows:
private void scrollToNext() {
if ((recyclerView.getLayoutManager()) != null) {
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(currentPosition++, 0);
}
}
You can use RelativeLayout or the custom layout instead of LinearLayout; according to what you're using in your RecyclerView
Similarly, decrement it if you want the previous one
private void scrollToPrevious() {
if ((recyclerView.getLayoutManager()) != null) {
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(currentPosition--, 0);
}
}

Cannot add a RelativeLayout to a RelativeLayout programmatically

So I'm trying to add a RelativeLayout to a RelativeLayout however, when I run my app, it's an IllegalStateException that shows this error: The specified child already has a parent. You must call removeView() on the child's parent first. I'm sure you guys have seen this before. My question is how do I properly nest two relative layouts together?
Here is the code snippet that produces the exception:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
RelativeLayout newFrame = new RelativeLayout(vidRipperService.getBaseContext());
newFrame.setLayoutParams(layoutParams);
// configure image view constraints...
// have the frame be right in the center of the layout.
ImageView editedFrame = new ImageView(vidRipperService.getBaseContext());
// Note: when doing padding the height and the width must be a multiple of two. A nice example is 70+30 = 100/2 = 50, but 80+30 = 110/2 = 55 <- not a multiple of two. Keep this in mind.
editedFrame.setId(View.generateViewId());
editedFrame.setPadding(30,30,30,0); // padding of 30 around the whole view.
editedFrame.setImageBitmap(frame); // set the frame to be that of the actual background.
RelativeLayout.LayoutParams frameLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
frameLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); // place frames in center of the view.
editedFrame.setLayoutParams(frameLayoutParams);
newFrame.addView(breakingNewsLayout); // add the breaking news layout to this view!
newFrame.addView(editedFrame);
The problem is specifically triggered from the second to last line newFrame.addView(breakingNewsLayout) That line triggers the exception. The breakingNewsLayout is another relative layout that I would like to add to newFrame. I would appreciate any knowledge on how to get this to work. I never ran into a problem when nesting layouts before, but for some reason, this is really not playing nice.
Here is the code that creates the breakingNewsLayout:
private void createBreakingNewsLayout()
{
breakingNewsLayout = new RelativeLayout(vidRipperService.getBaseContext()); // create the new breaking new layout.
breakingNewsLayout.setElevation(5);
breakingNewsLayout.setPadding(0,0,0,15);
breakingNewsLayout.setBackgroundColor(ContextCompat.getColor(vidRipperService, R.color.transparent)); // ensure that the background is transparent.
// MATCH_PARENT for both width and height so that banner is shown on the frame for the video.
RelativeLayout.LayoutParams breakingNewsParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
breakingNewsParams.setMargins(0,50,0,0); // todo: ensure that the margin is 50dp not pixels!
breakingNewsParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
breakingNewsLayout.setLayoutParams(breakingNewsParams); // set the layout params for the breaking news layout.
// set all of the text view attributes.
TextView liveBannerText = getLiveBannerText();
TextView breakingNewsTime = getBreakingNewsTime();
TextView breakingNewsHeadline = getBreakingNewsHeadline(breakingNewsTime.getId()); // headline goes about the breaking news time.
TextView breakingNewsBanner = getBreakingNewsBanner(breakingNewsHeadline.getId()); // banner goes above the breaking news headline
TextView viddyWatermarkText = getViddyWatermarkText(breakingNewsHeadline.getId()); // viddy watermark goes above the breaking news headline.
TextView breakingNewsDescription = getBreakingNewsDescription(breakingNewsTime.getId()); // breaking news description goes to the end of the breaking news time
// Add all of the views for the breaking news layout.
breakingNewsLayout.addView(liveBannerText);
breakingNewsLayout.addView(breakingNewsBanner);
breakingNewsLayout.addView(viddyWatermarkText);
breakingNewsLayout.addView(breakingNewsHeadline);
breakingNewsLayout.addView(breakingNewsTime);
breakingNewsLayout.addView(breakingNewsDescription);
}
maybe you should remove breakingNewsLayout before you add it:
((ViewGroup) breakingNewsLayout.getParent()).removeView(breakingNewsLayout);
I figured it out! After extensive researching and testing the reason I was getting this issue was because I was attempting to reuse the breakingNewsLayout when creating a new frame. I have x amount of frames and I needed to generate the breakingNewsLayout every single time I wanted to apply the layout to the frame. Since I was trying to reuse the layout that I have already added, the layout already has a parent and thus the exception above was called.
Apologies for the question and any lack of details.

How to disable OnClickListerners

I am developing an app where the user has to match the image and corresponding name of it correctly.
My problem is when the user selects the image first and selects the wrong name it will display wrong answer and if he selects the answer it will be displayed correct answer.
The user should not have to re-select the image again
I have made the onClickListerner's null but it wont work some of my code is as follows,
txt_tag[0] = (TextView) findViewById(R.id.txt_tag1);
txt_tag[0].setOnClickListener(this);
txt_tag[0].setTypeface(tf);
txt_tag[1] = (TextView) findViewById(R.id.txt_tag2);
txt_tag[1].setOnClickListener(this);
txt_tag[1].setTypeface(tf);
txt_tag[2] = (TextView) findViewById(R.id.txt_tag3);
txt_tag[2].setOnClickListener(this);
txt_tag[2].setTypeface(tf);
txt_tag[3] = (TextView) findViewById(R.id.txt_tag4);
txt_tag[3].setOnClickListener(this);
txt_tag[3].setTypeface(tf);
img[0] = (ImageButton) findViewById(R.id.img1);
img[0].setOnClickListener(this);
img[1] = (ImageButton) findViewById(R.id.img2);
img[1].setOnClickListener(this);
img[2] = (ImageButton) findViewById(R.id.img3);
img[2].setOnClickListener(this);
img[3] = (ImageButton) findViewById(R.id.img4);
img[3].setOnClickListener(this);
btn_nxt = (Button) findViewById(R.id.btn_next);
btn_nxt.setOnClickListener(this);
and I have called an method inside that method where I have made all onClickListerner's null
txt_tag[0].setOnClickListener(null);
txt_tag[1].setOnClickListener(null);
txt_tag[2].setOnClickListener(null);
txt_tag[3].setOnClickListener(null);
img[0].setOnClickListener(null);
img[1].setOnClickListener(null);
img[2].setOnClickListener(null);
img[3].setOnClickListener(null);
Can anyone tell me where I am going wrong or any modifications I can do to it.
Thanks in advance
Try using
txt_tag[0].setClickable(false);
txt_tag[1].setClickable(false);
..
img[0].setClickable(false);
img[1].setClickable(false);
..
Your question is not that clear.. but if you want your image and text tag not clickable.. make them android:clickable="false" in xml or setClickable(false);
If I were you I would be checking that logic in a listener. So if the quiestion (if it's a quiz) is in the state "ANSWERED", don't react to event.
Your question is unclear, but I understand it as follows:
You have a bunch of ImageViews and a bunch of TextViews and a Mapping between them.
You want to be able to first select an ImageView, then a TextView. If they match, "correct answer" will be displayed somewhere, if not, "wrong answer" will be displayed
If you click on a TextView before an ImageView is selected, nothing happens
If you click on a Textview and another TextView is already selected, nothing happens
If that is correct, you can do this like this: You keep two variables
int selectedImage = -1;
int selectedText = -1;
In your OnClickListener you update their values like this:
if (source instanceof ImageViews) {
selectedImage = getArrayIndex(source); // I guess you already have a method to retrieve the index
selectedText = -1; // reset textSelection
} else {
if (selectedText < 0) {
selectedText = getArrayIndex(source);
}
}
updateAnswerTextView(); // here you check if the two selections (selectedText and selectedImage) match and display the corresponding string.
Instead, you could just iterate through the TextView array and call
setClickable(false);
on every element as soon as one is clicked. If a new image is selected, you will have to set them to clickable again.
EDIT: And I agree with Rob, you should not remove your Listeners to achieve this behaviour.
Here's my suggestion, if you want you code up specific behaviour you can use the onClickListener callback to achieve what you want.
In the listener, check the state of the image; if it is already selected and you want to ignore the event then you just exit from your callback.
I think setting the onClickListener to null is the wrong thing to do.

Android Development: How To Get All EditText Children of a ViewGroup?

Basically, I have a LinearLayout that holds a random amount of horizontal LinearLayouts, and in each of the horizontal LinearLayouts there's a TextView and an EditText. I want to be able to get the value of each EditText children of the master LinearLayout.
Sorry if it's confusing, I'm no good at explaining things!
Could I just set the same ID for each of the EditTexts then use findViewById, or would that only return the first instance of an EditText?
Thanks,
Alex.
LinearLayout ll = //Your Layout this can be any Linear or Relative layout
//in which you added your spinners at runtime ;
int count = ll.getChildCount();
for(int i =0;i<count;i++)
{
View v = ll.getChildAt(i);
if(v instanceof Spinner)
{
// you got the spinner
EditText s = (EditText) v;
Log.i("Item selected",s.getText().toString());
}
}
findViewById returns only the first view with the given id. You're going to have to traverse the view hierarchy yourself, at least until you get down to each horizontal linear layout. You'll find the methods ViewGroup.getChildCount() and ViewGroup.getChildAt(int) useful for this.
You would need to call findViewById on each of the LinearLayouts. If you do this, you can set the same ID for each EditText.

Categories