how to refresh a RecyclerView draw (not datas)? - java

In a RecyclerView, I change the presentation for some items as follows:
if (stk.getQty() == 0) { // mise en valeur des stocks à 0 non purgeables
cellStockQty.setTextColor(Color.RED);
GradientDrawable border = new GradientDrawable();
border.setColor(mIV.getResources().getColor(R.color.colorAugment)); // white background
border.setStroke(1, mIV.getResources().getColor(R.color.colorAccent)); // black border with full
mIV.setBackground(border);
}
When I delete an item, I manage to remove it from the display, with notifyItemRemoved(index); but the next item takes the presentation of the item that was deleted.
Of course, if I leave this activity then come back, all is right.
How to make sure to refresh the display, depending on the data?
before deleting Jjjjjj item
after deleting Jjjjjj item
Edit:
Here is my original layout
<androidx.cardview.widget.CardView 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="wrap_content"
android:layout_margin="0dp"
android:foreground="#drawable/card_foreground"
app:cardBackgroundColor="#color/stockRecyclerviewBackground"
app:cardCornerRadius="6dp"
app:cardElevation="4dp"
app:cardMaxElevation="6dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<include layout="#layout/recystock_cell_include" />
</androidx.cardview.widget.CardView>

Make sure to clear background mIV.setBackground(null);
in else statement.

Your onBindViewHolder is broken. A properly written onBindViewHolder sets EVERY field of the view that could possibly change. And in a proper RecyclerView implementation, non of the click handlers or other actions ever touch the view itself, they all change the model then notify the adapter an iten has changed. Obviously you're not doing that- you're inheriting some of the styling from the old view. Fix your onBindViewHolder to specify all of the view information.

It seems that just doing:
mStockRecyclerView.setAdapter(mAdapter);
is enough.
Sorry for the noise.
Another solution, found with the help of the answers here and there Reset Button to default background is to reset the background, using setTag() and getTag() like:
if ( mIV.getTag() == null ) mIV.setTag(mIV.getBackground());
if (cellStockQty.getTag() == null ) cellStockQty.setTag(cellStockQty.getCurrentTextColor());
if (stk.getQty() == 0) { // mise en valeur des stocks à 0 non purgeables
cellStockQty.setTextColor(Color.RED);
GradientDrawable border = new GradientDrawable();
border.setColor(mIV.getResources().getColor(R.color.colorAugment)); // white background
border.setStroke(1, mIV.getResources().getColor(R.color.colorAccent)); // black border with full
mIV.setBackground(border);
} else {
cellStockQty.setTextColor((int)cellStockQty.getTag());
mIV.setBackground((Drawable) mIV.getTag());
}

Related

FlexboxLayout.getFlexLines() is 0 until after UI is updated

I'm trying to programmatically add views to a FlexboxLayout. When the layout has reached 3 wrapped lined, I want to stop adding things to the layout. The maxLine attribute wasn't useful as it starts to add too much on each horizontal line.
<com.google.android.flexbox.FlexboxLayout
android:id="#+id/dynamic_button_layout"
android:layout_width="wrap_content"
android:layout_height="584dp"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:animateLayoutChanges="true"
android:orientation="horizontal"
app:alignContent="center"
app:alignItems="center"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="center"/>
I initially tried the following in onCreate
int viewNumber = 0;
for (Button button : buttons){
flexboxLayout.addView(button);
if (flexboxLayout.getFlexLines().size() > 2){
flexboxLayout.removeViewAt(viewNumber);
break;
}
viewNumber++;
}
The idea being if I've gone onto the 4th flex line, I just remove the last view and stop adding more views. The issue is that .getFlexLines() is always empty
If I do something like this, however, I the flex lines are returned correctly and I can start removing views. The problem with this is you can very briefly see the 4th line of buttons before they're removed.
getWindow().getDecorView().post(new Runnable() {
#Override
public void run() {
final FlexboxLayout flexboxLayout = findViewById(R.id.dynamic_button_layout);
int lines = flexboxLayout.getFlexLines().size(); // this will be 4
}
});
Is there any way to get the number of flex lines before the UI is actually updated?

Determine if a TextView requires scrolling

Inside CursorAdapter's bindView() I bind data to the following layout:
A TextView and two Buttons : "UP" and "DOWN".
The TextView is defined in XML like so:
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingTop="25dp"
android:scrollbars="vertical"
android:textAlignment="textStart"
android:textColor="#5c6284"
app:autoSizeMaxTextSize="40sp"
app:autoSizeMinTextSize="20sp"
app:autoSizeTextType="uniform" />
A vertical scrolling behavior is applied to the TextView, which is being controlled by the "UP and "DOWN" Buttons.
I would like to determine if the TextView requires scrolling ( is long enough to not fit its provided drawing area ) so that I can enable/disable the "UP" and "DOWN" buttons accordingly.
I'm currently reading BaseMovementMethod's scrollDown function, thinking of applying its measuring logic to my adapter, though I have the feeling that it should be much simpler. Maybe a built in behavior that I'm not aware of.
Is there a better way to achieve this, other than my suggested approach?
What I would do is put the textview inside a scrollview like so:
<ScrollView
android:id="#+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test texts here"/>
</ScrollView>
In your activity, execute these lines:
boolean needScrolling = false;
if(scroller.getHeight() < tv_content.getHeight()) needScrolling = true;
You can use Static Layout class. If you set it up with your TextView's parameters you'll be able to calculate the height of the rendered text.
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;
StaticLayout myStaticLayout = new StaticLayout(text, myTextView.getPaint(), myTextView.getWidth(), alignment, spacingMultiplier, spacingAddition, includePadding);
float height = myStaticLayout.getHeight();
Then you can compare the height of your text and height of your TextView and figure out if it will require scrolling or not.
You can also try to manually create a Paint object with your min text size if myTextView.getPaint() approach does not work.
Calculate mTextView's height without data and with data and then compare it
mTextView.post(new Runnable() {
#Override
public void run() {
int lineHeight=mTextView.getCompoundPaddingBottom()+ mTextView.getCompoundPaddingTop()+mTextView.getLineHeight();
int height=mTextView.getHeight()-(mTextView.getCompoundPaddingTop()+mTextView.getLineHeight());
if (height>lineHeight){
}
}
});

Getting real color of a ViewGroup and compare with resource color

I am trying to get color of a ViewGroup and trying to compare with a resource color.
Here is my code
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="#+id/mainLayout"
android:background="#color/colorPrimary"
android:layout_height="match_parent"
>
In my code i am doing this.
ViewGroup mainLayout = (ViewGroup) findViewById(R.id.mainLayout);
ColorDrawable viewColor = (ColorDrawable) mainLayout.getBackground();
if (viewColor != null)
{
int colorId = viewColor.getColor(); // i get -6371612
int mainColor = getResources().getColor(R.color.colorPrimary); // i get -65536
if (colorId == mainColor)
{
mainLayout.setBackgroundColor(Color.RED);
}
}
The colorId and mainColor are not same. What am i missing? shouldn't they be same?
I just checked your code and it works flawlessly (the colors get compared and are equal).
BUT: when I set the background color of the RelativeLayout to Color.RED I also get the -65536 the you received.
So to put it another way: your code works fine, but the function gets called twice, the first time it sets the color of the layout to red (as the code instructs it to) and then when you try to check the colors don't match up (since one is red and the other is colorPrimary.

Android - ScrollView with TextView auto scrolling

I have a TextView within a ScrollView, which currently scrolls to the bottom of the TextView.
The TextView is filled dynamically constantly updating (the TextView is essentially acting as an actions console).
However, the problem I am having is that when the dynamic text is added to the ScrollView, the user can scroll past the text into black space, which is increasing everytime more content is added to the TextView.
I have tried various different apporaches however none of these gave the right outcome. I cannot use maxLines or define height of the layouts as I need this to be dynamic for the various screen sizes, which the number of lines visible constantly changing.
I had also orginally done this progromatically, however this was crashing at random time and therefore would like to keep it in my layout (better usabilty), example code below:
final int scrollAmount = update.getLayout().getLineTop(update.getLineCount()) - update.getHeight();
if(scrollAmount > 0)
{
update.scrollTo(0, scrollAmount);
}
The code below is my current layout xml being used to automatically scroll my TextView to the bottom as content is added:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/spacer2"
android:layout_below="#+id/spacer1"
android:fillViewport="true" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/battle_details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="12dp"
android:layout_gravity="bottom" />
</LinearLayout>
</ScrollView>
EDIT - This is the code I am using to add text to my TextView:
private void CreateConsoleString()
{
TextView update = (TextView)findViewById(R.id.battle_details);
String ConsoleString = "";
// BattleConsole is an ArrayList<String>
for(int i = 0; i < BattleConsole.size(); i++)
{
ConsoleString += BattleConsole.get(i) + "\n";
}
update.setText(ConsoleString);
}
EDIT 2 - I add content to the BattleConsole like this:
BattleConsole.add("Some console text was added");
CreateConsoleString();
To sum up my only issue is the ScrollView and/or TextView is adding blank space to the bottom rather than stop the user from scrolling at the last line of text. Any help or guidence as to where I am going wrong would be much appreciated.
It looks like that when you call
BattleConsole.get(i)
it sometimes returns an empty String so you are just basically adding new lines to your TextView.
You can do this for example:
StringBuilder consoleString = new StringBuilder();
// I'm using a StringBuilder here to avoid creating a lot of `String` objects
for(String element : BattleConsole) {
// I'm assuming element is not null
if(!"".equals(element)) {
consoleString.append(element);
consoleString.append(System.getProperty("line.separator")); // I'm using a constant here.
}
}
update.setText(consoleString.toString());
If you could post the code of BattleConsole I could help you more.
As a footnote: it is encouraged to use camelCase in java. Only class names start with capital letters in java according to the convention.

Strange behaviour in Expandablelistview - Android

Im trying to implement an activity that uses ExpandableListView and I have gotten so far but now I have found some strange behavior.
My activity is meant to record food intake as specified by the user. they have a choice of menus (breakfast, lunch and dinner - the outer group) which expand to show their contents.
when a user clicks on an inner menu item a dialog appears asking them for the qty. once they enter a qty and dismiss the dialog the text on the menu item changes to reflect the quantity of that item that has been consumed
The above image shows the list in a closed state.
below is the list after I have opened the lunch menu and clicked on 'Potato Chips' and indicating a Quantity of 1. As you can see the 'Potato' itemtext has now been changed to reflect the Qty of 1.
The strange part happens now. if I click on 'Lunch' and close the list and then click on it again re-opening it, the 'Qty X 1' text has jumped to another item (Milk)
each time I open and close the list it jumps back and forth between the two items. Also if I open up other items, such as breakfast, I find that they too have now gotten items with 'Qty X 1' even though I havent clicked them.
The bits of code that are relevant are as such:
The XML for a child element:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="#+id/childname"
android:paddingLeft="50dip"
android:textSize="14dip"
android:textStyle="italic"
android:layout_width="200dip"
android:textColor="#color/black"
android:layout_height="40dip"/>
<TextView android:id="#+id/qty_display"
android:text="-"
android:textSize="14dip"
android:textStyle="italic"
android:layout_width="50dip"
android:textColor="#color/black"
android:layout_height="wrap_content"/>
</LinearLayout>
The code thats triggered on clicking a child element:
public boolean onChildClick(
ExpandableListView parent,
View v,
int groupPosition,
int childPosition,
long id) {
// open the dialog and inflate the buttons
myDialog = new Dialog(this);
myDialog.setTitle("Food Item Qty");
myDialog.setContentView(R.layout.food_intake_dialog);
final Button ok = (Button)myDialog.findViewById(R.id.fi_ok_but);
Button cancel = (Button)myDialog.findViewById(R.id.fi_cancel_but);
//the id for this item is stored as a hash key in a map (say, item_id01)
String key = "item_id"+groupPosition+""+childPosition;
current_selected_food_item_id = Integer.parseInt(itemMap.get(key));
// inflate the textview that shows the qty for this item on the expandablelist
barQty = (TextView) v.findViewById(R.id.qty_display);
// set the ok button to record teh quantity on press
ok.setOnClickListener(new OnClickListener() {
public void onClick(View viewParam) {
//inflate the input box that receives quantity from user
EditText fiQty = (EditText) myDialog.findViewById(R.id.fiQty);
// get the quantity and append the text on hte list item
String qty = fiQty.getText().toString();
barQty.setText("Qty X "+qty);
//open the database and save state
FoodIntake.this.application.getFoodIntakeHelper().open();
FoodIntake.this.application.getFoodIntakeHelper().storeFoodIntakeLog(current_selected_food_item_id,qty,visit_id,remote_visit_id);
String log = FoodIntake.this.application.getFoodIntakeHelper().getFoodIntakeLog(visit_id);
FoodIntake.this.application.getFoodIntakeHelper().close();
// append the main food intake list and close the dialog
list.setText("Food Intake Log:\n\n"+log);
myDialog.cancel();
}
});
The above code opens a dialog, accepts a value for quantity, appends the list element to reflect this, also saves to database and sets a textview with the selected item and quantity.
Sorry to just dump a whole load of code, but this has me stumped and hopefully someone can help.
Thanks
Kevin
Android reuses dialogs. So the behavior you are seeing could be a result of that. You could use a activity managed dialog and use onPrepareDialog() to update dialog contents.
I don't think the problem is with the dialogs. I had the same problem in my project and couldn't fix it. I think the ExpandableListView has a bug when opening children. I had only one child per group and when I expand a group, the child moves to another group. After testing, I found out that when I expand the children are reloaded.

Categories