I have a horizontal recyclerview which implements ItemTouchHelper callback for dragging and reordering cells. When a cell is being moved i want to shrink all of the cells widths so they all appear on screen. In onItemSelected() i can successfully change the size of the cell currently being moved, and revert back in onItemClear.
However, i want to resize all cells and not just the current cell. What is the best approach for this?
I tried creating a function in my adapter class and calling it to resize via notifyDataSetChanged() however it was removing the current cell being moved.
Is there a way to do this as part of my ItemTouchHelperCallback - creating a similar function as onItemSelected but updating all other cells?
I am not sure if I completely understand what you are trying to do, but I think this might help:
int childs = recyclerView.getChildCount();
for (int i = 0; i < childs; i++) {
View child = recyclerView.getChildAt(i);
if (child != null) {
RecyclerView.ViewHolder vholder = recyclerView.getChildViewHolder(child);
if (vholder != null) {
ViewHolder holder = (ViewHolder) vholder;
if (holder.view != null) {
LayoutParams params = (LayoutParams)holder.view.getLayoutParams();
params.width = <new_width>;
params.height = <new_height>;
holder.view.setLayoutParams(params);
}
}
}
}
Happy coding !!
Related
I'm trying to make a tictactoe game using Android Studio. I already write a code to set the button visibility when someone is win (and it work). I also want the game to show "play again" button when the board is full but no one win (tie). How do i do that.
Here's what I'm trying to code:
public boolean checkGameState () {
boolean isBoardFull = false;
androidx.gridlayout.widget.GridLayout gridLayout = findViewById(R.id.gridLayout);
for (int i = 0; i < gridLayout.getChildCount(); i++) {
ImageView reset = (ImageView) gridLayout.getChildAt(i);
if(reset.getDrawable() != null) {
isBoardFull = true;
}
}
return isBoardFull;
}
Here's a screenshot of what the game look like:
as you can see in the image, the "Play again" button is visible even though the game hasn't been finished yet. The button will show if the someone is win or tie (the board is full).
There is slight mistake with your condition as once it found drawable it marks as isBoardFull as true, Which is wrong as all child haven't been checked yet so marking isBoardFull as true at this stage is wrong.
You can do like following:
public boolean checkGameState () {
boolean isBoardFull = true; // first mark it as full
androidx.gridlayout.widget.GridLayout gridLayout = findViewById(R.id.gridLayout);
for (int i = 0; i < gridLayout.getChildCount(); i++) {
ImageView reset = (ImageView) gridLayout.getChildAt(i);
if(reset.getDrawable() == null) {
isBoardFull = false; // if drawable not found that means it's not full
}
}
return isBoardFull;
}
So now first it will mark board as full but once any drawable is found as null it will mark board as empty.
I think you should initialize a variable isEveryChildChecked = true before iterating the gridLayout child.
While iterating the children, if a grid is not checked, set the field isEveryChildChecked = false.
Then after iteration, check the field isEveryChildChecked, If it is true, you can display play again else do nothing or hide the Play again button.
I Have the below layout.
<CoordinatorLayout>
<AppBarLayout>
<CollapsingToolbarLayout>
<Toolbar>
</CollapsingToolbarLayout>
<View1>
<View2>
</AppBarLayout>
<RecyclerView>(appbar_scrolling_view_behavior)
On one use case, I use an empty state viewholder to show that there are empty items from api.Also I have to hardcode the height of the recyclerview relative to the screenheight. As a result, on scrolling of the recyclerview fully up there is some space left below the empty state of the recyclerview.I do not want this space.Can anyone please help me?
recyclerview.scrollToPosition(0)
val params = appbar.layoutParams as CoordinatorLayout.LayoutParams
val behavior = params.behavior as AppBarLayout.Behavior?
if (behavior != null) {
val valueAnimator: ValueAnimator = ValueAnimator.ofInt()
valueAnimator.interpolator = DecelerateInterpolator()
valueAnimator.addUpdateListener { animation ->
behavior.topAndBottomOffset = (animation.animatedValue as Int)
appbar.requestLayout()
}
valueAnimator.setIntValues(
0, -appbar.totalScrollRange + view2.measuredHeight
)
valueAnimator.duration = 50
valueAnimator.start()
}
Found this approach to work after trying other approaches.
I am creating an app where I will be loading some images and data from a database, it should look like this:
Image______Name of user
Image______Name of user
Image______Name of user
etc..
I tried to create it just with a dummy image and some text to figure out how it works.
I create a LinearLayout, ImageView and a TextView, I add those two to the LinearLayout, and than I add that LinearLayout to a RelativeLayout.
The problem is, that all the images and text are placed in the same place, on top of each other. How can I change it so it is in the format I need?
relativeLayout = (RelativeLayout) findViewById(R.id.rel);
for(int i = 0; i< 30; i++)
{
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
TextView hello = new TextView(this);
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.mipmap.ic_launcher);
String hi = "Hey";
if(i == 0){hi = "Hello0";}
if(i == 2){hi = "Hello2";}
if(i == 3){hi = "Hello3";}
if(i == 4){hi = "Hello4";}
hello.setText(hi);
layout.addView(imageView);
layout.addView(hello);
relativeLayout.addView(layout);
}
I am using a for to loop it a few times just for test.
Instead of RecyclerView, add the items in a LinearLayout. You can also set position where to add the new item in the LinearLayout.
I would suggest you do instead is:
create a model object for the user details(name and picture)
Use ListView or RecyclerView with a simple adapter add items to an
ArrayList of model object and notify the adapter when data is
changed.
This way you'll be reusing the views, and that'll improve the performance much better.
for examples, you can take a look at these sample projects.
https://github.com/lokeshsaini94/SimpleAndroidExamples/tree/master/ListView
https://github.com/lokeshsaini94/SimpleAndroidExamples/tree/master/RecyclerView
Currently the list when populated is starting with the view # the bottom of the list. Is there a way using listAdapters to force it to the top of the list?
Currently the orientation scrolls to the bottom on create. Is there a way to pin the screen to the top when it creates? http://imgur.com/wGTEy in this example you see that entry 1 on create is shoved upwards to make room for six... Instead I want it to populate like this. http://imgur.com/6Lg6e... entry 1 is the top of the list and 6 is pushed off to the bottom for the scroll.
If you look at the picture above you will notice it starts at the bottom of the list instead of at the top. Any Ideas?
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings);
setListAdapter(mAdapter);
registerForContextMenu(getListView());
populateFields();
private void populateFields() {
if (mRowId != null) {
Cursor note = mDbHelper.fetchDaily(mRowId);
startManagingCursor(note);
String body = note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_DBODY));
mAdapter.clear();
if (!(body.trim().equals(""))){
String bodysplit[] = body.split(",");
for (int i = 0; i < bodysplit.length; i++) {
mAdapter.add(bodysplit[i].trim());
}
}
}
}
**edited to fix != string error.
You want the items later in the list to be at the top of the ListView? If so, check out this questions: Is it possible to make a ListView populate from the bottom?
You are completely changing the adapter, so the scroll position is lost in the process... You can use:
ListView listView = getListView();
int position = listView.getFirstVisiblePosition();
if (!(body.trim().equals(""))){
String bodysplit[] = body.split(",");
for (int i = 0; i < bodysplit.length; i++) {
mAdapter.add(bodysplit[i].trim());
}
}
listView.setSelection(position);
But this is not perfect as it is, if a row is added before position the index will be off. If your list contains unique values you can use ArrayAdapter#getPosition(), to find the new index.
While I still recommend using a CursorAdapter, because it handles large table data better, I want to address a point on efficiency with your ArrayAdapter code.
By using adapter.clear() and adapter.add() you are asking the ListView to redraw itself on every step... potentially dozens or hundreds of times. Instead you should work with the ArrayList directly and then ask the ListView to redraw once itself with ArrayAdapter#notifyDataSetChanged() after the loop completes.
I'm trying to set a font across all TextView's by iterating through the LinearLayout's views and using instanceof.
The form currently consists of 4 TextView's and one Button.
The below code is detecting all Views, even the Button as a TextView?
/* Set fonts */
LinearLayout ll = (LinearLayout) findViewById(R.id.ll_screenincourse_wrapper);
for (int i = 0; i < ll.getChildCount(); i++) {
View v = ll.getChildAt(i);
if (v instanceof TextView) {
((TextView) v).setTypeface(Fonts.get3dDumbFont(this));
}
}
If I log each view's class name it returns the TextView and the Button so I know the correct controls are being picked up.
The problem is the Button and TextView's fonts are being set, and I only want the TextView's.
I have found a work around and that is to do the following but am intrigued as to why the above code does not work as expected.
/* Set fonts */
LinearLayout ll = (LinearLayout) findViewById(R.id.ll_screenincourse_wrapper);
for (int i = 0; i < ll.getChildCount(); i++) {
View v = ll.getChildAt(i);
if (v.getClass().getName().contains("TextView")) {
((TextView) v).setTypeface(Fonts.get3dDumbFont(this));
}
}
Is it because both Button and TextView are of type View? If so, what would be the correct way about doing this?
Any help appreciated, thanks. Ricky.
Actually, Button is a subclass of TextView! That's why you see it as a TextView (it is also a TextView).
http://developer.android.com/reference/android/widget/Button.html
public class Button extends TextView
You could make a second if instanceof to exclude Buttons or use
if (v.getClass() == TextView.class)
But this won't match any other subclasses of TextView (if you use them).
It is simple
Button Class extends TextView Class
Check the documentaion