问:
Android Hello GridView Tutorial Will Not Display Images
First time poster!

I am new to Android development and have been following Google's HelloView tutorials without problems... until the HelloGridView tutorial. For some reason I cannot get any images to display, only a black background. I originally followed this tutorial:

http://developer.android.com/resources/tutorials/views/hello-gridview.html

but moved on to this nearly identical one:

http://developer.android.com/guide/tutorials/views/hello-gridview.html

in order to eliminate some added complexity by removing the OnItemClickListener code and narrow my possible problem areas. My code is exactly the same as the provided code, literally copied and pasted. I even downloaded the original sample files from the tutorial and placed them in the res\drawable folder, and the R code appears to have recognized them successfully and updated it's generated code accordingly. I am using Android target 1.5 and have tried this program both on my Droid X and using the Android emulator. I have all of my imports and the code compiles and runs fine. However, my activity displays only a black screen; no images appear. When I click on the black background, orange squares appear where the images should be. I found one or two posts mentioning this problem, but it was always coupled with some larger, more obvious problem and never addressed. I will list my code and LogCat below for reference.

I noticed that my LogCat mentioned:

```<code>WARN/ImageView(364): Unable to find resource: 2130837507
</code>```

which led me to this thread:
Why setImageResource displays nothing?
detailing a possible workaround using setImageDrawable instead of setImageResource. I implemented this using the following line of code:

```<code>imageView.setImageDrawable(mContext.getResources().getDrawable(mThumbIds[position]));
</code>```

however, that just resulted in a Resources$NotFoundException that crashed my code (also documented below).

IN CONCLUSION

I figure that an Android tutorial shouldn't require a workaround, so I'm guessing that I have some sort of configuration issue. After a few hours of searching and trying things, I haven't found a solution yet so I figured it warrants some discussion. Also, with this being my first post, please let me know if you see any glaring faux pas. I apologize in advance for the oncoming wall-o-code, though I figure too little data may be worse than too much. :D

Thanks Guys!

MarnBeast

UPDATE

I tried using R.drawable.icon in my mThumbIds, alternating between that and one of my pictures. None of the pictures showed up, but the icons did. I then tried a .png version of my picture, but that didn't work either. I copied the icon.png image and edited it in paint (put a mustache on the android guy :D) and saved it as dummyicon.png. I alternated between that and the icon, but that didn't work either. Finally, I got rid of all of the icon references, and just used my png image, but oddly, when run, ALL of the images showed up as the icon, even though I am not referencing it in mThumbIds! This differs from the previous behavior, when nothing at all was displayed. I changed a couple to the dummyicon, and when run, those images just didn't show up / were just black. All of the other images (the one png converted image repeated in mThumbIds) still showed up as icons.

Finally, I replaced my converted png image references with icon again, alternating between icon and dummyicon, and now neither of them show up - just a black screen again. So it appears that dummyicon and icon both yield nothing when referenced, just a black space, but my converted png image - chloie1.png - yields the icon.png. I added another picture - chloie2.png - and alternated between chloie1 and chloie2, but only chloie1 shows the icon image. Thus, this is the state of my mThumbIds as of now:

```<code>private Integer[] mThumbIds = {
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2
};
</code>```

and this is the output from the emulator:

SOLUTION!

As it turned out, for some reason this tutorial would not work for me with JPEG images. Furthermore, I made a dumb assumption and simply changed the extension from .jpg to .png, which still worked in image viewers but was still recognized as a jpg by android. Now that I have edited each picture in paint, then saved as a PNG type, everything seems to work fine.

HOWEVER I still feel that there is an issue here. I'm assuming that android should handle .jpg images considering that they provided jpegs as their sample pictures. If anyone has an idea as to why PNG works but JPG doesn't, please respond. In the mean time, this simple fix will do just fine.

Thanks for the help!

REFERENCES

main.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:columnWidth="90dp"
    android:numColumns="auto_fit"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
/>
</code>```

HelloGridViewActivity.java

```<code>package com.marnbeast.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class HelloGridViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setAdapter(new ImageAdapter(this));

    }
}
</code>```

ImageAdapter.java

```<code>package com.marnbeast.android;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // references to our images
    private Integer[] mThumbIds = {
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7
    };
}
</code>```

LogCat Unable to Find Resource:

```<code>07-24 06:00:04.564: WARN/ResourceType(364): getEntry failing because entryIndex 3 is beyond type entryCount 1
07-24 06:00:04.564: WARN/ResourceType(364): Failure getting entry for 0x7f020003 (t=1 e=3) in package 0: 0x80000001
07-24 06:00:04.584: WARN/ImageView(364): Unable to find resource: 2130837507
07-24 06:00:04.584: WARN/ImageView(364): android.content.res.Resources$NotFoundException: Resource ID #0x7f020003
07-24 06:00:04.584: WARN/ImageView(364):     at android.content.res.Resources.getValue(Resources.java:891)
07-24 06:00:04.584: WARN/ImageView(364):     at android.content.res.Resources.getDrawable(Resources.java:579)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.ImageView.resolveUri(ImageView.java:485)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.ImageView.setImageResource(ImageView.java:270)
07-24 06:00:04.584: WARN/ImageView(364):     at com.marnbeast.android.ImageAdapter.getView(ImageAdapter.java:41)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.AbsListView.obtainView(AbsListView.java:1274)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.GridView.onMeasure(GridView.java:934)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:464)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewRoot.performTraversals(ViewRoot.java:763)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
07-24 06:00:04.584: WARN/ImageView(364):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-24 06:00:04.584: WARN/ImageView(364):     at android.os.Looper.loop(Looper.java:123)
07-24 06:00:04.584: WARN/ImageView(364):     at android.app.ActivityThread.main(ActivityThread.java:4363)
07-24 06:00:04.584: WARN/ImageView(364):     at java.lang.reflect.Method.invokeNative(Native Method)
07-24 06:00:04.584: WARN/ImageView(364):     at java.lang.reflect.Method.invoke(Method.java:521)
07-24 06:00:04.584: WARN/ImageView(364):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
07-24 06:00:04.584: WARN/ImageView(364):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
07-24 06:00:04.584: WARN/ImageView(364):     at dalvik.system.NativeStart.main(Native Method)
</code>```

LogCat Resource Not Fount Exception After Workaround with .setImageDrawable:

```<code>    07-24 07:02:50.234: ERROR/AndroidRuntime(390): Uncaught handler: thread main exiting due to uncaught exception
07-24 07:02:50.245: ERROR/AndroidRuntime(390): android.content.res.Resources$NotFoundException: Resource ID #0x7f020003
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.content.res.Resources.getValue(Resources.java:891)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.content.res.Resources.getDrawable(Resources.java:579)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.marnbeast.android.ImageAdapter.getView(ImageAdapter.java:40)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.AbsListView.obtainView(AbsListView.java:1274)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.GridView.onMeasure(GridView.java:934)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:464)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewRoot.performTraversals(ViewRoot.java:763)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.os.Looper.loop(Looper.java:123)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.app.ActivityThread.main(ActivityThread.java:4363)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at java.lang.reflect.Method.invokeNative(Native Method)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at java.lang.reflect.Method.invoke(Method.java:521)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at dalvik.system.NativeStart.main(Native Method)
</code>```

EDIT: I'm including the R file to verify that the images are correctly referenced.

```<code>/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.marnbeast.android;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
        public static final int sample_0=0x7f020001;
        public static final int sample_1=0x7f020002;
        public static final int sample_2=0x7f020003;
        public static final int sample_3=0x7f020004;
        public static final int sample_4=0x7f020005;
        public static final int sample_5=0x7f020006;
        public static final int sample_6=0x7f020007;
        public static final int sample_7=0x7f020008;
    }
    public static final class id {
        public static final int gridview=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}
</code>```

答:
we can use this code,

```<code>public class MyGridView extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animalsgridview);
GridView gridview = (GridView) findViewById(R.id.gridviewid);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
        int imageId = ((ImageAdapter)parent.getAdapter()).mygetItemId(position);

        Intent fullScreenIntent = new Intent(v.getContext(),Full.class);
        fullScreenIntent.putExtra(Full.class.getName(),imageId);
        AnimalsGridView.this.startActivity(fullScreenIntent);
        }
    });
}
private class ImageAdapter extends BaseAdapter {
    private Context mContext;
    public ImageAdapter(Context c) {
    mContext = c;
    }
    public int getCount() {
        return imagearray.length;
    }
    public Object getItem(int position) {
        return null;
    }
    public long getItemId(int position) {
        return imagearray[position];
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setPadding(1, 1, 1, 1);

        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(imagearray[position]);
        return imageView;
    }
    // references to our images
    private Integer[] imagearray = {

        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7,
        R.drawable.sample_0, R.drawable.sample_1,
        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7,
        R.drawable.sample_0, R.drawable.sample_1,
        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7

        };
    public int mygetItemId(int position) {
                return imagearray[position];
    }
  }
}
</code>```

this is the xml code

```<code><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_weight="1"
  android:layout_height="fill_parent">
<GridView
    android:id="@+id/gridviewid"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="auto_fit"
    android:columnWidth="60dp"
    android:stretchMode="columnWidth"
    android:padding="5dp"
    android:verticalSpacing="5dp"
    android:horizontalSpacing="20dp"
    android:gravity="center_horizontal"
    android:background="#ffffff"/>
</code>```

Body:
First time poster!

I am new to Android development and have been following Google's HelloView tutorials without problems... until the HelloGridView tutorial. For some reason I cannot get any images to display, only a black background. I originally followed this tutorial:

http://developer.android.com/resources/tutorials/views/hello-gridview.html

but moved on to this nearly identical one:

http://developer.android.com/guide/tutorials/views/hello-gridview.html

in order to eliminate some added complexity by removing the OnItemClickListener code and narrow my possible problem areas. My code is exactly the same as the provided code, literally copied and pasted. I even downloaded the original sample files from the tutorial and placed them in the res\drawable folder, and the R code appears to have recognized them successfully and updated it's generated code accordingly. I am using Android target 1.5 and have tried this program both on my Droid X and using the Android emulator. I have all of my imports and the code compiles and runs fine. However, my activity displays only a black screen; no images appear. When I click on the black background, orange squares appear where the images should be. I found one or two posts mentioning this problem, but it was always coupled with some larger, more obvious problem and never addressed. I will list my code and LogCat below for reference.

I noticed that my LogCat mentioned:

WARN/ImageView(364): Unable to find resource: 2130837507

which led me to this thread:
Why setImageResource displays nothing?
detailing a possible workaround using setImageDrawable instead of setImageResource. I implemented this using the following line of code:

imageView.setImageDrawable(mContext.getResources().getDrawable(mThumbIds[position]));

however, that just resulted in a Resources$NotFoundException that crashed my code (also documented below).

IN CONCLUSION

I figure that an Android tutorial shouldn't require a workaround, so I'm guessing that I have some sort of configuration issue. After a few hours of searching and trying things, I haven't found a solution yet so I figured it warrants some discussion. Also, with this being my first post, please let me know if you see any glaring faux pas. I apologize in advance for the oncoming wall-o-code, though I figure too little data may be worse than too much. :D

Thanks Guys!

MarnBeast

UPDATE

I tried using R.drawable.icon in my mThumbIds, alternating between that and one of my pictures. None of the pictures showed up, but the icons did. I then tried a .png version of my picture, but that didn't work either. I copied the icon.png image and edited it in paint (put a mustache on the android guy :D) and saved it as dummyicon.png. I alternated between that and the icon, but that didn't work either. Finally, I got rid of all of the icon references, and just used my png image, but oddly, when run, ALL of the images showed up as the icon, even though I am not referencing it in mThumbIds! This differs from the previous behavior, when nothing at all was displayed. I changed a couple to the dummyicon, and when run, those images just didn't show up / were just black. All of the other images (the one png converted image repeated in mThumbIds) still showed up as icons.

Finally, I replaced my converted png image references with icon again, alternating between icon and dummyicon, and now neither of them show up - just a black screen again. So it appears that dummyicon and icon both yield nothing when referenced, just a black space, but my converted png image - chloie1.png - yields the icon.png. I added another picture - chloie2.png - and alternated between chloie1 and chloie2, but only chloie1 shows the icon image. Thus, this is the state of my mThumbIds as of now:

private Integer[] mThumbIds = {
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2,
        R.drawable.chloie1, R.drawable.chloie2
};

and this is the output from the emulator:

SOLUTION!

As it turned out, for some reason this tutorial would not work for me with JPEG images. Furthermore, I made a dumb assumption and simply changed the extension from .jpg to .png, which still worked in image viewers but was still recognized as a jpg by android. Now that I have edited each picture in paint, then saved as a PNG type, everything seems to work fine.

HOWEVER I still feel that there is an issue here. I'm assuming that android should handle .jpg images considering that they provided jpegs as their sample pictures. If anyone has an idea as to why PNG works but JPG doesn't, please respond. In the mean time, this simple fix will do just fine.

Thanks for the help!

REFERENCES

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:columnWidth="90dp"
    android:numColumns="auto_fit"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
/>

HelloGridViewActivity.java

package com.marnbeast.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class HelloGridViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setAdapter(new ImageAdapter(this));

    }
}

ImageAdapter.java

package com.marnbeast.android;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // references to our images
    private Integer[] mThumbIds = {
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7
    };
}

LogCat Unable to Find Resource:

07-24 06:00:04.564: WARN/ResourceType(364): getEntry failing because entryIndex 3 is beyond type entryCount 1
07-24 06:00:04.564: WARN/ResourceType(364): Failure getting entry for 0x7f020003 (t=1 e=3) in package 0: 0x80000001
07-24 06:00:04.584: WARN/ImageView(364): Unable to find resource: 2130837507
07-24 06:00:04.584: WARN/ImageView(364): android.content.res.Resources$NotFoundException: Resource ID #0x7f020003
07-24 06:00:04.584: WARN/ImageView(364):     at android.content.res.Resources.getValue(Resources.java:891)
07-24 06:00:04.584: WARN/ImageView(364):     at android.content.res.Resources.getDrawable(Resources.java:579)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.ImageView.resolveUri(ImageView.java:485)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.ImageView.setImageResource(ImageView.java:270)
07-24 06:00:04.584: WARN/ImageView(364):     at com.marnbeast.android.ImageAdapter.getView(ImageAdapter.java:41)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.AbsListView.obtainView(AbsListView.java:1274)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.GridView.onMeasure(GridView.java:934)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:464)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 06:00:04.584: WARN/ImageView(364):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.View.measure(View.java:7964)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewRoot.performTraversals(ViewRoot.java:763)
07-24 06:00:04.584: WARN/ImageView(364):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
07-24 06:00:04.584: WARN/ImageView(364):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-24 06:00:04.584: WARN/ImageView(364):     at android.os.Looper.loop(Looper.java:123)
07-24 06:00:04.584: WARN/ImageView(364):     at android.app.ActivityThread.main(ActivityThread.java:4363)
07-24 06:00:04.584: WARN/ImageView(364):     at java.lang.reflect.Method.invokeNative(Native Method)
07-24 06:00:04.584: WARN/ImageView(364):     at java.lang.reflect.Method.invoke(Method.java:521)
07-24 06:00:04.584: WARN/ImageView(364):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
07-24 06:00:04.584: WARN/ImageView(364):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
07-24 06:00:04.584: WARN/ImageView(364):     at dalvik.system.NativeStart.main(Native Method)

LogCat Resource Not Fount Exception After Workaround with .setImageDrawable:

    07-24 07:02:50.234: ERROR/AndroidRuntime(390): Uncaught handler: thread main exiting due to uncaught exception
07-24 07:02:50.245: ERROR/AndroidRuntime(390): android.content.res.Resources$NotFoundException: Resource ID #0x7f020003
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.content.res.Resources.getValue(Resources.java:891)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.content.res.Resources.getDrawable(Resources.java:579)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.marnbeast.android.ImageAdapter.getView(ImageAdapter.java:40)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.AbsListView.obtainView(AbsListView.java:1274)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.GridView.onMeasure(GridView.java:934)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:464)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.View.measure(View.java:7964)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewRoot.performTraversals(ViewRoot.java:763)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.os.Looper.loop(Looper.java:123)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at android.app.ActivityThread.main(ActivityThread.java:4363)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at java.lang.reflect.Method.invokeNative(Native Method)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at java.lang.reflect.Method.invoke(Method.java:521)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
07-24 07:02:50.245: ERROR/AndroidRuntime(390):     at dalvik.system.NativeStart.main(Native Method)

EDIT: I'm including the R file to verify that the images are correctly referenced.

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.marnbeast.android;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
        public static final int sample_0=0x7f020001;
        public static final int sample_1=0x7f020002;
        public static final int sample_2=0x7f020003;
        public static final int sample_3=0x7f020004;
        public static final int sample_4=0x7f020005;
        public static final int sample_5=0x7f020006;
        public static final int sample_6=0x7f020007;
        public static final int sample_7=0x7f020008;
    }
    public static final class id {
        public static final int gridview=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}

Body:
we can use this code,

public class MyGridView extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animalsgridview);
GridView gridview = (GridView) findViewById(R.id.gridviewid);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
        int imageId = ((ImageAdapter)parent.getAdapter()).mygetItemId(position);

        Intent fullScreenIntent = new Intent(v.getContext(),Full.class);
        fullScreenIntent.putExtra(Full.class.getName(),imageId);
        AnimalsGridView.this.startActivity(fullScreenIntent);
        }
    });
}
private class ImageAdapter extends BaseAdapter {
    private Context mContext;
    public ImageAdapter(Context c) {
    mContext = c;
    }
    public int getCount() {
        return imagearray.length;
    }
    public Object getItem(int position) {
        return null;
    }
    public long getItemId(int position) {
        return imagearray[position];
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setPadding(1, 1, 1, 1);

        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(imagearray[position]);
        return imageView;
    }
    // references to our images
    private Integer[] imagearray = {

        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7,
        R.drawable.sample_0, R.drawable.sample_1,
        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7,
        R.drawable.sample_0, R.drawable.sample_1,
        R.drawable.sample_2, R.drawable.sample_3,
        R.drawable.sample_4, R.drawable.sample_5,
        R.drawable.sample_6, R.drawable.sample_7

        };
    public int mygetItemId(int position) {
                return imagearray[position];
    }
  }
}

this is the xml code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_weight="1"
  android:layout_height="fill_parent">
<GridView
    android:id="@+id/gridviewid"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="auto_fit"
    android:columnWidth="60dp"
    android:stretchMode="columnWidth"
    android:padding="5dp"
    android:verticalSpacing="5dp"
    android:horizontalSpacing="20dp"
    android:gravity="center_horizontal"
    android:background="#ffffff"/>


来源: stackexchange

问:
How can I select an element and the text that follows it with jQuery?
I'm trying to find a class within a sentence and wrap it along with remainder of the text in the sentence.

What I want:

  text text text text text text text text text text text text text text text
  text text text text text text text text

TEST
 text
  text text text text text text text text text text text text text text text

```
<p>One of the many efforts I've tried:</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>$('.test').each(function() {
  $(this).nextUntil('div').addBack().wrap('<div class="newWrap"></div>');
});</code>```

    text text text text text text text text text text text text text text text
    text text text text text text text text
TEST
 text
    text text text text text text text text text text text text text text text

```

答:
If the text is always at the end, this seems to work.

$('.test').each(function() {
  const thisEl = $(this);
  const content = thisEl.parent().contents();
  const text = content[content.length - 1];
  $(text).add(thisEl).wrapAll('
');
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.container {
  border-top: 2px solid #ccc;
  margin-top: 10px;
  padding-top: 10px;
}

.pink {
  background-color: pink;
}</code>```

  before before before before before before before before before before before

TEST
 after after after after after after after after

  before before before before before before before before before before before

between between

TEST
 after after after after after after after after

way before

  before before before before before before before before before before before

between between

TEST
 after after after after after after after after

```

ContentLicense: CC BY-SA 4.0

Body:
I'm trying to find a class within a sentence and wrap it along with remainder of the text in the sentence.

What I want:

  text text text text text text text text text text text text text text text
  text text text text text text text text

TEST
 text
  text text text text text text text text text text text text text text text

One of the many efforts I've tried:

$('.test').each(function() {
  $(this).nextUntil('div').addBack().wrap('

');
});

    text text text text text text text text text text text text text text text
    text text text text text text text text
TEST
 text
    text text text text text text text text text text text text text text text

Body:
If the text is always at the end, this seems to work.

$('.test').each(function() {
  const thisEl = $(this);
  const content = thisEl.parent().contents();
  const text = content[content.length - 1];
  $(text).add(thisEl).wrapAll('<div class="pink">');
});

.container {
  border-top: 2px solid #ccc;
  margin-top: 10px;
  padding-top: 10px;
}

.pink {
  background-color: pink;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
  before before before before before before before before before before before
  <div class="test">TEST</div> after after after after after after after after
</div>

<div class="container">
  before before before before before before before before before before before
  <div class="other">between between</div>
  <div class="test">TEST</div> after after after after after after after after
</div>

<div class="container">
  <div class="other">way before</div>
  before before before before before before before before before before before
  <div class="other">between between</div>
  <div class="test">TEST</div> after after after after after after after after
</div>


问:
Trying to insert value in class method
I'm trying to pass an argument from the get_name() to post() and I'm not sure how to do this correctly</p>
```<code>from bs4 import BeautifulSoup
import requests

webhook = 'my webhook'

class Item:
    def __init__(self, url):
        self.url = url
        self.page = requests.get(url)
        self.soup = BeautifulSoup(self.page.content, 'html.parser')

    def post(self):
        requests.post(webhook, json={'username' : 'scraper', 'content' : variable}) #how do i do this

    def get_name(self):
        name = self.soup.find('h2').get_text()
        post(name)

    def get_price(self):
        price = self.soup.find('span' {'class' : 'text-lg wait-for-i18n-format-render'})
        post(price)
</code>```

答:
I guess, you want something like this:

from bs4 import BeautifulSoup
import requests

webhook = 'my webhook'

class Item:
    def __init__(self, url):
        self.url = url
        self.page = requests.get(url)
        self.soup = BeautifulSoup(self.page.content, 'html.parser')

    def post(self, data):
        requests.post(webhook, json={'username' : 'scraper', 'content' : data})

    def get_name(self):
        name = self.soup.find('h2').get_text()
        self.post(name)
```

Title: Trying to insert value in class method

Body:
I'm trying to pass an argument from the get_name() to post() and I'm not sure how to do this correctly

from bs4 import BeautifulSoup
import requests

webhook = 'my webhook'

class Item:
    def __init__(self, url):
        self.url = url
        self.page = requests.get(url)
        self.soup = BeautifulSoup(self.page.content, 'html.parser')

    def post(self):
        requests.post(webhook, json={'username' : 'scraper', 'content' : variable}) #how do i do this

    def get_name(self):
        name = self.soup.find('h2').get_text()
        post(name)

    def get_price(self):
        price = self.soup.find('span' {'class' : 'text-lg wait-for-i18n-format-render'})
        post(price)


问:
recyclerView layout grid items not aligning properly
i don't know much about java, just started, so i will have difficulties understanding the answers. emli5.

screenshot:

expected output:

in the recyclerview (right), these items are not aligning up like i want them to.

I want that each cell has a fixed size, and maximum number of columns possible in the grid.
spacing b/w each cell (both vertical and horizontal) is equal to (left space) divided by (number of columns minus one).   [with no extra space left at start, top, bottom or end]

here is the code:

package com.MyStickersWA.DogeStickers;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.drawee.view.SimpleDraweeView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

@SuppressWarnings("ALL")
public class StickerPackDetailsActivity extends AddStickerPackActivity {

    /**
     * Do not change below values of below 3 lines as this is also used by WhatsApp
     */
    public static final String EXTRA_STICKER_PACK_ID = "sticker_pack_id";
    public static final String EXTRA_STICKER_PACK_AUTHORITY = "sticker_pack_authority";
    public static final String EXTRA_STICKER_PACK_NAME = "sticker_pack_name";

    public static final String EXTRA_STICKER_PACK_WEBSITE = "sticker_pack_website";
    public static final String EXTRA_STICKER_PACK_EMAIL = "sticker_pack_email";
    public static final String EXTRA_STICKER_PACK_PRIVACY_POLICY = "sticker_pack_privacy_policy";
    public static final String EXTRA_STICKER_PACK_LICENSE_AGREEMENT = "sticker_pack_license_agreement";
    public static final String EXTRA_STICKER_PACK_TRAY_ICON = "sticker_pack_tray_icon";
    public static final String EXTRA_SHOW_UP_BUTTON = "show_up_button";
    public static final String EXTRA_STICKER_PACK_DATA = "sticker_pack";

    private RecyclerView recyclerView;
    private GridLayoutManager layoutManager;
    private StickerPreviewAdapter stickerPreviewAdapter;
    private int numColumns;
    private View addButton;
    private View infoButton;
    private View backButton;
    private View alreadyAdded;
    private StickerPack stickerPack;
    private WhiteListCheckAsyncTask whiteListCheckAsyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sticker_pack_details);

        AdView mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        MobileAds.initialize(this, initializationStatus -> { });

        mAdView.loadAd(adRequest);

        boolean showUpButton = getIntent().getBooleanExtra(EXTRA_SHOW_UP_BUTTON, false);
        stickerPack = getIntent().getParcelableExtra(EXTRA_STICKER_PACK_DATA);
        TextView packNameTextView = findViewById(R.id.pack_name);
        TextView packPublisherTextView = findViewById(R.id.author);
        ImageView packTrayIcon = findViewById(R.id.tray_image);
        TextView packSizeTextView = findViewById(R.id.pack_size);
        TextView stickersQtyTextView = findViewById(R.id.stickers_qty);
        TextView stickersAnimatedView = findViewById(R.id.stickers_animated);
        ImageView stickersAnimatedImage = findViewById(R.id.sticker_pack_animation_indicator);
        SimpleDraweeView expandedStickerView = findViewById(R.id.sticker_details_expanded_sticker);

        addButton = findViewById(R.id.add_to_whatsapp_button);
        infoButton = findViewById(R.id.action_info);
        backButton = findViewById(R.id.action_back);
        alreadyAdded = findViewById(R.id.already_added_button);
        layoutManager = new GridLayoutManager(this, 1);
        recyclerView = findViewById(R.id.sticker_list);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(pageLayoutListener);

        if (stickerPreviewAdapter == null) {
            stickerPreviewAdapter = new StickerPreviewAdapter(getLayoutInflater(), R.drawable.sticker_error, getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size), getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_padding), stickerPack, expandedStickerView);
            recyclerView.setAdapter(stickerPreviewAdapter);
        }
        packNameTextView.setText(stickerPack.name);
        packPublisherTextView.setText(stickerPack.publisher);
        packTrayIcon.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile));
        packSizeTextView.setText(Formatter.formatShortFileSize(this, stickerPack.getTotalSize()));
        stickersQtyTextView.setText(stickerPack.getTotalQty() + "");
        addButton.setOnClickListener(v -> addStickerPackToWhatsApp(stickerPack.identifier, stickerPack.name));
        infoButton.setOnClickListener(v -> onOptionsItemSelected());
        backButton.setOnClickListener(v -> finish());

        if (stickerPack.animatedStickerPack) {
            Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.animated_indicator_vector);
            stickersAnimatedImage.setImageURI(animatedIcon);
            stickersAnimatedView.setText("Animated");
        } else {
            Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.static_indicator_vector);
            stickersAnimatedImage.setImageURI(animatedIcon);
            stickersAnimatedView.setText("Static");
        }
    }

    private void launchInfoActivity(String publisherWebsite, String publisherEmail, String privacyPolicyWebsite, String licenseAgreementWebsite, String trayIconUriString) {
        Intent intent = new Intent(StickerPackDetailsActivity.this, StickerPackInfoActivity.class);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, stickerPack.identifier);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_WEBSITE, publisherWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_EMAIL, publisherEmail);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_PRIVACY_POLICY, privacyPolicyWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_LICENSE_AGREEMENT, licenseAgreementWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_TRAY_ICON, trayIconUriString);
        startActivity(intent);
    }

    public boolean onOptionsItemSelected() {
        if (stickerPack != null) {
            Uri trayIconUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile);
            launchInfoActivity(stickerPack.publisherWebsite, stickerPack.publisherEmail, stickerPack.privacyPolicyWebsite, stickerPack.licenseAgreementWebsite, trayIconUri.toString());
            return true;
        }
        return false;
    }

    private final ViewTreeObserver.OnGlobalLayoutListener pageLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int imgSize = recyclerView.getContext().getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size);
            int recyclerViewWidth = recyclerView.getWidth();

            int numColumns = recyclerViewWidth / imgSize;
            int colSpacing = (recyclerViewWidth - (numColumns * imgSize)) / (numColumns - 1);
//            int colSpacing = recyclerView.getWidth() - imgSize * numColumns;

            setNumColumns(numColumns, colSpacing);
        }
    };

    @SuppressLint("NotifyDataSetChanged")
    private void setNumColumns(int numColumns, int colSpacing) {
        if (this.numColumns != numColumns) {

//            recyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 2, 2));
            layoutManager.setSpanCount(numColumns);
            recyclerView.setLayoutManager(layoutManager);

            this.numColumns = numColumns;
            if (stickerPreviewAdapter != null) {
                stickerPreviewAdapter.notifyDataSetChanged();
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        whiteListCheckAsyncTask = new WhiteListCheckAsyncTask(this);
        whiteListCheckAsyncTask.execute(stickerPack);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (whiteListCheckAsyncTask != null && !whiteListCheckAsyncTask.isCancelled()) {
            whiteListCheckAsyncTask.cancel(true);
        }
    }

    private void updateAddUI(Boolean isWhitelisted) {
        if (isWhitelisted) {
            addButton.setVisibility(View.GONE);
            alreadyAdded.setVisibility(View.VISIBLE);
        } else {
            addButton.setVisibility(View.VISIBLE);
            alreadyAdded.setVisibility(View.GONE);
        }
    }

    static class WhiteListCheckAsyncTask extends AsyncTask<StickerPack, Void, Boolean> {
        private final WeakReference<StickerPackDetailsActivity> stickerPackDetailsActivityWeakReference;

        WhiteListCheckAsyncTask(StickerPackDetailsActivity stickerPackListActivity) {
            this.stickerPackDetailsActivityWeakReference = new WeakReference<>(stickerPackListActivity);
        }

        @Override
        protected final Boolean doInBackground(StickerPack... stickerPacks) {
            StickerPack stickerPack = stickerPacks[0];
            final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
            if (stickerPackDetailsActivity == null) {
                return false;
            }
            return WhitelistCheck.isWhitelisted(stickerPackDetailsActivity, stickerPack.identifier);
        }

        @Override
        protected void onPostExecute(Boolean isWhitelisted) {
            final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
            if (stickerPackDetailsActivity != null) {
                stickerPackDetailsActivity.updateAddUI(isWhitelisted);
            }
        }
    }
}
```
<pre class="lang-java prettyprint-override"><code>/*
 * Copyright (c) WhatsApp Inc. and its affiliates.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.MyStickersWA.DogeStickers;

import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;

public class StickerPreviewAdapter extends RecyclerView.Adapter<StickerPreviewViewHolder> {

    private static final float COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA = 1f;
    private static final float EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA = 0.2f;

    @NonNull
    private final StickerPack stickerPack;

    private final int cellSize;
    private final int cellLimit;
    private final int cellPadding;
    private final int errorResource;
    private final SimpleDraweeView expandedStickerPreview;

    private final LayoutInflater layoutInflater;
    private RecyclerView recyclerView;
    private View clickedStickerPreview;
    float expandedViewLeftX;
    float expandedViewTopY;

    StickerPreviewAdapter(
            @NonNull final LayoutInflater layoutInflater,
            final int errorResource,
            final int cellSize,
            final int cellPadding,
            @NonNull final StickerPack stickerPack,
            final SimpleDraweeView expandedStickerView) {
        this.cellSize = cellSize;
        this.cellPadding = cellPadding;
        this.cellLimit = 0;
        this.layoutInflater = layoutInflater;
        this.errorResource = errorResource;
        this.stickerPack = stickerPack;
        this.expandedStickerPreview = expandedStickerView;
    }

    @NonNull
    @Override
    public StickerPreviewViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, final int i) {
        View itemView = layoutInflater.inflate(R.layout.sticker_image_item, viewGroup, false);
        StickerPreviewViewHolder vh = new StickerPreviewViewHolder(itemView);

        ViewGroup.LayoutParams layoutParams = vh.stickerPreviewView.getLayoutParams();
        layoutParams.height = cellSize;
        layoutParams.width = cellSize;
        vh.stickerPreviewView.setLayoutParams(layoutParams);
        vh.stickerPreviewView.setPadding(cellPadding, cellPadding, cellPadding, cellPadding);

        return vh;
    }

    @Override
    public void onBindViewHolder(@NonNull final StickerPreviewViewHolder stickerPreviewViewHolder, final int i) {
        stickerPreviewViewHolder.stickerPreviewView.setImageResource(errorResource);
        stickerPreviewViewHolder.stickerPreviewView.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(i).imageFileName));
        stickerPreviewViewHolder.stickerPreviewView.setOnClickListener(v -> expandPreview(i, stickerPreviewViewHolder.stickerPreviewView));
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
        recyclerView.addOnScrollListener(hideExpandedViewScrollListener);
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        recyclerView.removeOnScrollListener(hideExpandedViewScrollListener);
        this.recyclerView = null;
    }

    private final RecyclerView.OnScrollListener hideExpandedViewScrollListener =
            new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    if (dx != 0 || dy != 0) {
                        hideExpandedStickerPreview();
                    }
                }
            };

    private void positionExpandedStickerPreview(int selectedPosition) {
        if (expandedStickerPreview != null) {
            // Calculate the view's center (x, y), then use expandedStickerPreview's height and
            // width to
            // figure out what where to position it.
            final ViewGroup.MarginLayoutParams recyclerViewLayoutParams =
                    ((ViewGroup.MarginLayoutParams) recyclerView.getLayoutParams());
            final int recyclerViewLeftMargin = recyclerViewLayoutParams.leftMargin;
            final int recyclerViewRightMargin = recyclerViewLayoutParams.rightMargin;
            final int recyclerViewWidth = recyclerView.getWidth();
            final int recyclerViewHeight = recyclerView.getHeight();

            final StickerPreviewViewHolder clickedViewHolder =
                    (StickerPreviewViewHolder)
                            recyclerView.findViewHolderForAdapterPosition(selectedPosition);
            if (clickedViewHolder == null) {
                hideExpandedStickerPreview();
                return;
            }
            clickedStickerPreview = clickedViewHolder.itemView;
            final float clickedViewCenterX =
                    clickedStickerPreview.getX()
                            + recyclerViewLeftMargin
                            + clickedStickerPreview.getWidth() / 2f;
            final float clickedViewCenterY =
                    clickedStickerPreview.getY() + clickedStickerPreview.getHeight() / 2f;

            expandedViewLeftX = clickedViewCenterX - expandedStickerPreview.getWidth() / 2f;
            expandedViewTopY = clickedViewCenterY - expandedStickerPreview.getHeight() / 2f;

            // If the new x or y positions are negative, anchor them to 0 to avoid clipping
            // the left side of the device and the top of the recycler view.
            expandedViewLeftX = Math.max(expandedViewLeftX, 0);
            expandedViewTopY = Math.max(expandedViewTopY, 0);

            // If the bottom or right sides are clipped, we need to move the top left positions
            // so that those sides are no longer clipped.
            final float adjustmentX =
                    Math.max(
                            expandedViewLeftX
                                    + expandedStickerPreview.getWidth()
                                    - recyclerViewWidth
                                    - recyclerViewRightMargin,
                            0);
            final float adjustmentY =
                    Math.max(expandedViewTopY + expandedStickerPreview.getHeight() - recyclerViewHeight, 0);

            expandedViewLeftX -= adjustmentX;
            expandedViewTopY -= adjustmentY;

            expandedStickerPreview.setX(expandedViewLeftX);
            expandedStickerPreview.setY(expandedViewTopY);
        }
    }

    private void expandPreview(int position, View clickedStickerPreview) {
        if (isStickerPreviewExpanded()) {
            hideExpandedStickerPreview();
            return;
        }

        this.clickedStickerPreview = clickedStickerPreview;
        if (expandedStickerPreview != null) {
            positionExpandedStickerPreview(position);

            final Uri stickerAssetUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(position).imageFileName);
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setUri(stickerAssetUri)
                    .setAutoPlayAnimations(true)
                    .build();
            expandedStickerPreview.setImageResource(errorResource);
            expandedStickerPreview.setController(controller);

            expandedStickerPreview.setVisibility(View.VISIBLE);
            recyclerView.setAlpha(EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA);

            expandedStickerPreview.setOnClickListener(v -> hideExpandedStickerPreview());
        }
    }

    public void hideExpandedStickerPreview() {
        if (isStickerPreviewExpanded() && expandedStickerPreview != null) {
            clickedStickerPreview.setVisibility(View.VISIBLE);
            expandedStickerPreview.setVisibility(View.INVISIBLE);
            recyclerView.setAlpha(COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA);
        }
    }

    private boolean isStickerPreviewExpanded() {
        return expandedStickerPreview != null && expandedStickerPreview.getVisibility() == View.VISIBLE;
    }

    @Override
    public int getItemCount() {
        int numberOfPreviewImagesInPack;
        numberOfPreviewImagesInPack = stickerPack.getStickers().size();
        if (cellLimit > 0) {
            return Math.min(numberOfPreviewImagesInPack, cellLimit);
        }
        return numberOfPreviewImagesInPack;
    }
}
</code>```

thanks in advance

答:
You need to create a custom item decoration by extending RecyclerView.ItemDecoration. You can do something like this:

```<code>import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

private final int numberOfColumns;
private final int spacing;
private final boolean addSpacingToPerimeter;

public GridSpacingItemDecoration(int numberOfColumns, int spacing, boolean addSpacingToPerimeter) {
    this.numberOfColumns = numberOfColumns;
    this.spacing = spacing;
    this.addSpacingToPerimeter = addSpacingToPerimeter;
}

@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, RecyclerView parent, @NonNull RecyclerView.State state) {
    int position = parent.getChildAdapterPosition(view); // item position
    int column = position % numberOfColumns; // item column

    if (addSpacingToPerimeter) {
        outRect.left = spacing - column * spacing / numberOfColumns;
        outRect.right = (column + 1) * spacing / numberOfColumns;

        if (position < numberOfColumns) { // top edge
            outRect.top = spacing;
        }
        outRect.bottom = spacing; // item bottom
    } else {
        outRect.left = column * spacing / numberOfColumns;
        outRect.right = spacing - (column + 1) * spacing / numberOfColumns;
        if (position >= numberOfColumns) {
            outRect.top = spacing; // item top
        }
    }
}
}
</code>```

and then use it like this

```<code>int numberOfColumns = 3; // 3 columns
int spacing = 50; // 50px
boolean addSpacingToPerimeter = false;
recyclerView.addItemDecoration(new GridSpacingItemDecoration(numberOfColumns, spacing, addSpacingToPerimeter))
</code>```

The GridSpacingItemDecoration class takes as a parameter the number of columns, the spacing in pixel and a boolean value that specifies whether you want spacing to be added to the list's perimeter as well. This boolean if set to true will add the given spacing as a margin not only between the grid adapter's items, but also between the items and the whole recyclerView.

Keep in mind that spacing is in pixels. So if you want to use dp instead, you can convert dp to px using

```<code>Math.round(dpValue * getResources().getDisplayMetrics().density))
</code>```

Body:
i don't know much about java, just started, so i will have difficulties understanding the answers. emli5.

screenshot:

expected output:

in the recyclerview (right), these items are not aligning up like i want them to.

I want that each cell has a fixed size, and maximum number of columns possible in the grid.
spacing b/w each cell (both vertical and horizontal) is equal to (left space) divided by (number of columns minus one).   [with no extra space left at start, top, bottom or end]

here is the code:

package com.MyStickersWA.DogeStickers;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.drawee.view.SimpleDraweeView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

@SuppressWarnings("ALL")
public class StickerPackDetailsActivity extends AddStickerPackActivity {

    /**
     * Do not change below values of below 3 lines as this is also used by WhatsApp
     */
    public static final String EXTRA_STICKER_PACK_ID = "sticker_pack_id";
    public static final String EXTRA_STICKER_PACK_AUTHORITY = "sticker_pack_authority";
    public static final String EXTRA_STICKER_PACK_NAME = "sticker_pack_name";

    public static final String EXTRA_STICKER_PACK_WEBSITE = "sticker_pack_website";
    public static final String EXTRA_STICKER_PACK_EMAIL = "sticker_pack_email";
    public static final String EXTRA_STICKER_PACK_PRIVACY_POLICY = "sticker_pack_privacy_policy";
    public static final String EXTRA_STICKER_PACK_LICENSE_AGREEMENT = "sticker_pack_license_agreement";
    public static final String EXTRA_STICKER_PACK_TRAY_ICON = "sticker_pack_tray_icon";
    public static final String EXTRA_SHOW_UP_BUTTON = "show_up_button";
    public static final String EXTRA_STICKER_PACK_DATA = "sticker_pack";

    private RecyclerView recyclerView;
    private GridLayoutManager layoutManager;
    private StickerPreviewAdapter stickerPreviewAdapter;
    private int numColumns;
    private View addButton;
    private View infoButton;
    private View backButton;
    private View alreadyAdded;
    private StickerPack stickerPack;
    private WhiteListCheckAsyncTask whiteListCheckAsyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sticker_pack_details);

        AdView mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        MobileAds.initialize(this, initializationStatus -> { });

        mAdView.loadAd(adRequest);

        boolean showUpButton = getIntent().getBooleanExtra(EXTRA_SHOW_UP_BUTTON, false);
        stickerPack = getIntent().getParcelableExtra(EXTRA_STICKER_PACK_DATA);
        TextView packNameTextView = findViewById(R.id.pack_name);
        TextView packPublisherTextView = findViewById(R.id.author);
        ImageView packTrayIcon = findViewById(R.id.tray_image);
        TextView packSizeTextView = findViewById(R.id.pack_size);
        TextView stickersQtyTextView = findViewById(R.id.stickers_qty);
        TextView stickersAnimatedView = findViewById(R.id.stickers_animated);
        ImageView stickersAnimatedImage = findViewById(R.id.sticker_pack_animation_indicator);
        SimpleDraweeView expandedStickerView = findViewById(R.id.sticker_details_expanded_sticker);

        addButton = findViewById(R.id.add_to_whatsapp_button);
        infoButton = findViewById(R.id.action_info);
        backButton = findViewById(R.id.action_back);
        alreadyAdded = findViewById(R.id.already_added_button);
        layoutManager = new GridLayoutManager(this, 1);
        recyclerView = findViewById(R.id.sticker_list);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(pageLayoutListener);

        if (stickerPreviewAdapter == null) {
            stickerPreviewAdapter = new StickerPreviewAdapter(getLayoutInflater(), R.drawable.sticker_error, getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size), getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_padding), stickerPack, expandedStickerView);
            recyclerView.setAdapter(stickerPreviewAdapter);
        }
        packNameTextView.setText(stickerPack.name);
        packPublisherTextView.setText(stickerPack.publisher);
        packTrayIcon.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile));
        packSizeTextView.setText(Formatter.formatShortFileSize(this, stickerPack.getTotalSize()));
        stickersQtyTextView.setText(stickerPack.getTotalQty() + "");
        addButton.setOnClickListener(v -> addStickerPackToWhatsApp(stickerPack.identifier, stickerPack.name));
        infoButton.setOnClickListener(v -> onOptionsItemSelected());
        backButton.setOnClickListener(v -> finish());

        if (stickerPack.animatedStickerPack) {
            Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.animated_indicator_vector);
            stickersAnimatedImage.setImageURI(animatedIcon);
            stickersAnimatedView.setText("Animated");
        } else {
            Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.static_indicator_vector);
            stickersAnimatedImage.setImageURI(animatedIcon);
            stickersAnimatedView.setText("Static");
        }
    }

    private void launchInfoActivity(String publisherWebsite, String publisherEmail, String privacyPolicyWebsite, String licenseAgreementWebsite, String trayIconUriString) {
        Intent intent = new Intent(StickerPackDetailsActivity.this, StickerPackInfoActivity.class);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, stickerPack.identifier);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_WEBSITE, publisherWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_EMAIL, publisherEmail);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_PRIVACY_POLICY, privacyPolicyWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_LICENSE_AGREEMENT, licenseAgreementWebsite);
        intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_TRAY_ICON, trayIconUriString);
        startActivity(intent);
    }

    public boolean onOptionsItemSelected() {
        if (stickerPack != null) {
            Uri trayIconUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile);
            launchInfoActivity(stickerPack.publisherWebsite, stickerPack.publisherEmail, stickerPack.privacyPolicyWebsite, stickerPack.licenseAgreementWebsite, trayIconUri.toString());
            return true;
        }
        return false;
    }

    private final ViewTreeObserver.OnGlobalLayoutListener pageLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int imgSize = recyclerView.getContext().getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size);
            int recyclerViewWidth = recyclerView.getWidth();

            int numColumns = recyclerViewWidth / imgSize;
            int colSpacing = (recyclerViewWidth - (numColumns * imgSize)) / (numColumns - 1);
//            int colSpacing = recyclerView.getWidth() - imgSize * numColumns;

            setNumColumns(numColumns, colSpacing);
        }
    };

    @SuppressLint("NotifyDataSetChanged")
    private void setNumColumns(int numColumns, int colSpacing) {
        if (this.numColumns != numColumns) {

//            recyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 2, 2));
            layoutManager.setSpanCount(numColumns);
            recyclerView.setLayoutManager(layoutManager);

            this.numColumns = numColumns;
            if (stickerPreviewAdapter != null) {
                stickerPreviewAdapter.notifyDataSetChanged();
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        whiteListCheckAsyncTask = new WhiteListCheckAsyncTask(this);
        whiteListCheckAsyncTask.execute(stickerPack);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (whiteListCheckAsyncTask != null && !whiteListCheckAsyncTask.isCancelled()) {
            whiteListCheckAsyncTask.cancel(true);
        }
    }

    private void updateAddUI(Boolean isWhitelisted) {
        if (isWhitelisted) {
            addButton.setVisibility(View.GONE);
            alreadyAdded.setVisibility(View.VISIBLE);
        } else {
            addButton.setVisibility(View.VISIBLE);
            alreadyAdded.setVisibility(View.GONE);
        }
    }

    static class WhiteListCheckAsyncTask extends AsyncTask<StickerPack, Void, Boolean> {
        private final WeakReference<StickerPackDetailsActivity> stickerPackDetailsActivityWeakReference;

        WhiteListCheckAsyncTask(StickerPackDetailsActivity stickerPackListActivity) {
            this.stickerPackDetailsActivityWeakReference = new WeakReference<>(stickerPackListActivity);
        }

        @Override
        protected final Boolean doInBackground(StickerPack... stickerPacks) {
            StickerPack stickerPack = stickerPacks[0];
            final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
            if (stickerPackDetailsActivity == null) {
                return false;
            }
            return WhitelistCheck.isWhitelisted(stickerPackDetailsActivity, stickerPack.identifier);
        }

        @Override
        protected void onPostExecute(Boolean isWhitelisted) {
            final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
            if (stickerPackDetailsActivity != null) {
                stickerPackDetailsActivity.updateAddUI(isWhitelisted);
            }
        }
    }
}

/*
 * Copyright (c) WhatsApp Inc. and its affiliates.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.MyStickersWA.DogeStickers;

import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;

public class StickerPreviewAdapter extends RecyclerView.Adapter<StickerPreviewViewHolder> {

    private static final float COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA = 1f;
    private static final float EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA = 0.2f;

    @NonNull
    private final StickerPack stickerPack;

    private final int cellSize;
    private final int cellLimit;
    private final int cellPadding;
    private final int errorResource;
    private final SimpleDraweeView expandedStickerPreview;

    private final LayoutInflater layoutInflater;
    private RecyclerView recyclerView;
    private View clickedStickerPreview;
    float expandedViewLeftX;
    float expandedViewTopY;

    StickerPreviewAdapter(
            @NonNull final LayoutInflater layoutInflater,
            final int errorResource,
            final int cellSize,
            final int cellPadding,
            @NonNull final StickerPack stickerPack,
            final SimpleDraweeView expandedStickerView) {
        this.cellSize = cellSize;
        this.cellPadding = cellPadding;
        this.cellLimit = 0;
        this.layoutInflater = layoutInflater;
        this.errorResource = errorResource;
        this.stickerPack = stickerPack;
        this.expandedStickerPreview = expandedStickerView;
    }

    @NonNull
    @Override
    public StickerPreviewViewHolder onCreateViewHolder(@NonNull final ViewGroup viewGroup, final int i) {
        View itemView = layoutInflater.inflate(R.layout.sticker_image_item, viewGroup, false);
        StickerPreviewViewHolder vh = new StickerPreviewViewHolder(itemView);

        ViewGroup.LayoutParams layoutParams = vh.stickerPreviewView.getLayoutParams();
        layoutParams.height = cellSize;
        layoutParams.width = cellSize;
        vh.stickerPreviewView.setLayoutParams(layoutParams);
        vh.stickerPreviewView.setPadding(cellPadding, cellPadding, cellPadding, cellPadding);

        return vh;
    }

    @Override
    public void onBindViewHolder(@NonNull final StickerPreviewViewHolder stickerPreviewViewHolder, final int i) {
        stickerPreviewViewHolder.stickerPreviewView.setImageResource(errorResource);
        stickerPreviewViewHolder.stickerPreviewView.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(i).imageFileName));
        stickerPreviewViewHolder.stickerPreviewView.setOnClickListener(v -> expandPreview(i, stickerPreviewViewHolder.stickerPreviewView));
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
        recyclerView.addOnScrollListener(hideExpandedViewScrollListener);
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
        recyclerView.removeOnScrollListener(hideExpandedViewScrollListener);
        this.recyclerView = null;
    }

    private final RecyclerView.OnScrollListener hideExpandedViewScrollListener =
            new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    if (dx != 0 || dy != 0) {
                        hideExpandedStickerPreview();
                    }
                }
            };

    private void positionExpandedStickerPreview(int selectedPosition) {
        if (expandedStickerPreview != null) {
            // Calculate the view's center (x, y), then use expandedStickerPreview's height and
            // width to
            // figure out what where to position it.
            final ViewGroup.MarginLayoutParams recyclerViewLayoutParams =
                    ((ViewGroup.MarginLayoutParams) recyclerView.getLayoutParams());
            final int recyclerViewLeftMargin = recyclerViewLayoutParams.leftMargin;
            final int recyclerViewRightMargin = recyclerViewLayoutParams.rightMargin;
            final int recyclerViewWidth = recyclerView.getWidth();
            final int recyclerViewHeight = recyclerView.getHeight();

            final StickerPreviewViewHolder clickedViewHolder =
                    (StickerPreviewViewHolder)
                            recyclerView.findViewHolderForAdapterPosition(selectedPosition);
            if (clickedViewHolder == null) {
                hideExpandedStickerPreview();
                return;
            }
            clickedStickerPreview = clickedViewHolder.itemView;
            final float clickedViewCenterX =
                    clickedStickerPreview.getX()
                            + recyclerViewLeftMargin
                            + clickedStickerPreview.getWidth() / 2f;
            final float clickedViewCenterY =
                    clickedStickerPreview.getY() + clickedStickerPreview.getHeight() / 2f;

            expandedViewLeftX = clickedViewCenterX - expandedStickerPreview.getWidth() / 2f;
            expandedViewTopY = clickedViewCenterY - expandedStickerPreview.getHeight() / 2f;

            // If the new x or y positions are negative, anchor them to 0 to avoid clipping
            // the left side of the device and the top of the recycler view.
            expandedViewLeftX = Math.max(expandedViewLeftX, 0);
            expandedViewTopY = Math.max(expandedViewTopY, 0);

            // If the bottom or right sides are clipped, we need to move the top left positions
            // so that those sides are no longer clipped.
            final float adjustmentX =
                    Math.max(
                            expandedViewLeftX
                                    + expandedStickerPreview.getWidth()
                                    - recyclerViewWidth
                                    - recyclerViewRightMargin,
                            0);
            final float adjustmentY =
                    Math.max(expandedViewTopY + expandedStickerPreview.getHeight() - recyclerViewHeight, 0);

            expandedViewLeftX -= adjustmentX;
            expandedViewTopY -= adjustmentY;

            expandedStickerPreview.setX(expandedViewLeftX);
            expandedStickerPreview.setY(expandedViewTopY);
        }
    }

    private void expandPreview(int position, View clickedStickerPreview) {
        if (isStickerPreviewExpanded()) {
            hideExpandedStickerPreview();
            return;
        }

        this.clickedStickerPreview = clickedStickerPreview;
        if (expandedStickerPreview != null) {
            positionExpandedStickerPreview(position);

            final Uri stickerAssetUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(position).imageFileName);
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setUri(stickerAssetUri)
                    .setAutoPlayAnimations(true)
                    .build();
            expandedStickerPreview.setImageResource(errorResource);
            expandedStickerPreview.setController(controller);

            expandedStickerPreview.setVisibility(View.VISIBLE);
            recyclerView.setAlpha(EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA);

            expandedStickerPreview.setOnClickListener(v -> hideExpandedStickerPreview());
        }
    }

    public void hideExpandedStickerPreview() {
        if (isStickerPreviewExpanded() && expandedStickerPreview != null) {
            clickedStickerPreview.setVisibility(View.VISIBLE);
            expandedStickerPreview.setVisibility(View.INVISIBLE);
            recyclerView.setAlpha(COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA);
        }
    }

    private boolean isStickerPreviewExpanded() {
        return expandedStickerPreview != null && expandedStickerPreview.getVisibility() == View.VISIBLE;
    }

    @Override
    public int getItemCount() {
        int numberOfPreviewImagesInPack;
        numberOfPreviewImagesInPack = stickerPack.getStickers().size();
        if (cellLimit > 0) {
            return Math.min(numberOfPreviewImagesInPack, cellLimit);
        }
        return numberOfPreviewImagesInPack;
    }
}

thanks in advance

Body:
You need to create a custom item decoration by extending RecyclerView.ItemDecoration. You can do something like this:

import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

private final int numberOfColumns;
private final int spacing;
private final boolean addSpacingToPerimeter;

public GridSpacingItemDecoration(int numberOfColumns, int spacing, boolean addSpacingToPerimeter) {
    this.numberOfColumns = numberOfColumns;
    this.spacing = spacing;
    this.addSpacingToPerimeter = addSpacingToPerimeter;
}

@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, RecyclerView parent, @NonNull RecyclerView.State state) {
    int position = parent.getChildAdapterPosition(view); // item position
    int column = position % numberOfColumns; // item column

    if (addSpacingToPerimeter) {
        outRect.left = spacing - column * spacing / numberOfColumns;
        outRect.right = (column + 1) * spacing / numberOfColumns;

        if (position < numberOfColumns) { // top edge
            outRect.top = spacing;
        }
        outRect.bottom = spacing; // item bottom
    } else {
        outRect.left = column * spacing / numberOfColumns;
        outRect.right = spacing - (column + 1) * spacing / numberOfColumns;
        if (position >= numberOfColumns) {
            outRect.top = spacing; // item top
        }
    }
}
}

and then use it like this

int numberOfColumns = 3; // 3 columns
int spacing = 50; // 50px
boolean addSpacingToPerimeter = false;
recyclerView.addItemDecoration(new GridSpacingItemDecoration(numberOfColumns, spacing, addSpacingToPerimeter))

The GridSpacingItemDecoration class takes as a parameter the number of columns, the spacing in pixel and a boolean value that specifies whether you want spacing to be added to the list's perimeter as well. This boolean if set to true will add the given spacing as a margin not only between the grid adapter's items, but also between the items and the whole recyclerView.

Keep in mind that spacing is in pixels. So if you want to use dp instead, you can convert dp to px using

Math.round(dpValue * getResources().getDisplayMetrics().density))


问:
Extract elements from dynamic list as increases or decreases in python3
Hello i have a dynamic list which increases or decreases accordingly from the extracted data from a site with BeautifulSoup

```<code>mylist = [a,b,c,d,.......]
</code>```

how can i make the following fstring to be dynamic as the list increases or decreases?

```<code>fstr = print(f"the forecast for the week is (choose number): {nl}1. {mylist[0]}{nl}2. {mylist[1]}{nl}3. {mylist[2]}{nl}4. {mylist[3]}{nl}5. Show all week")
</code>```

As you can see i want the elements of mylist to be seperated by \nl (new line) in the fstring and not join it to a string. Is this possible?

the Output is

```<code>the forecast for the week is (choose number):
1. Tuesday 08  2022
2. Wednesday 09  2022
3. Thursday 10  2022
4. Friday 11  2022
</code>```

答:
You can use a list comprehension and enumerate() to create the dynamic list and join() the elements by new line character:

```<code>mylist = ['Tuesday 08  2022','Wednesday 09  2022','Thursday 10  2022','Friday 11  2022']

data = '\n'.join([f"{i}. {e}" for i,e in enumerate(mylist,start=1)])

print(f"the forecast for the week is (choose number):\n{data}")
</code>```

Output

```<code>the forecast for the week is (choose number):
1. Tuesday 08  2022
2. Wednesday 09  2022
3. Thursday 10  2022
4. Friday 11  2022
</code>```

Body:
Hello i have a dynamic list which increases or decreases accordingly from the extracted data from a site with BeautifulSoup

mylist = [a,b,c,d,.......]

how can i make the following fstring to be dynamic as the list increases or decreases?

fstr = print(f"the forecast for the week is (choose number): {nl}1. {mylist[0]}{nl}2. {mylist[1]}{nl}3. {mylist[2]}{nl}4. {mylist[3]}{nl}5. Show all week")

As you can see i want the elements of mylist to be seperated by \nl (new line) in the fstring and not join it to a string. Is this possible?

the Output is

the forecast for the week is (choose number):
1. Tuesday 08  2022
2. Wednesday 09  2022
3. Thursday 10  2022
4. Friday 11  2022

Body:
You can use a list comprehension and enumerate() to create the dynamic list and join() the elements by new line character:

mylist = ['Tuesday 08  2022','Wednesday 09  2022','Thursday 10  2022','Friday 11  2022']

data = '\n'.join([f"{i}. {e}" for i,e in enumerate(mylist,start=1)])

print(f"the forecast for the week is (choose number):\n{data}")

Output

the forecast for the week is (choose number):
1. Tuesday 08  2022
2. Wednesday 09  2022
3. Thursday 10  2022
4. Friday 11  2022


问:
Typescript and useRef hook causing type error
I made a custom Checkbox component to handle events differently, code below:

```<code>const DoubleClickCheckbox = ({ filter, handleDoubleClick, handleSingleClick }: DCCheckboxProps) => {
  const delay = 400;
  const timer = useRef(null);

  const classes = useStyles();
  const flags = useFlags();

  useEffect(() => {
    return () => {
      timer.current && clearTimeout(timer.current);
    };
  }, []);

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  const onClick = (e) => {
    if (flags.csRequireFilters) {
      e.stopPropagation();
      handleSingleClick(filter);
      return;
    }

    switch (e.detail) {
      case 1:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        timer.current = setTimeout(() => {
          handleSingleClick(filter);
        }, delay);
        break;
      case 2:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        clearTimeout(timer.current);
        handleDoubleClick(filter);
        break;
      default:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        clearTimeout(timer.current);
        return;
    }
  };

  return (
    <div className={classes.filter} onClick={onClick} onKeyDown={() => {}} role="button" tabIndex={0}>
      <Checkbox
        label={filter.label}
        className={classes.checkbox_custom}
        checked={filter.selected}
        checkedIcon={filter.mandatory ? <Icons.CheckboxDoubleClick /> : <Icons.CheckboxSingleClick />}
      />
    </div>
  );
};
</code>```

I would like to dump my eslint-disable-next-line @typescript-eslint/ban-ts-comment and ts-ignore.

If I rewrite my code it reads as below, I get a typescript error:

```<code>  case 1:
    timer.current = setTimeout(() => {
      handleSingleClick(filter);
    }, delay);
    break;
</code>```

The error is: Type 'Timeout' is not assignable to type 'null'. I have tried various other tricks, for example: const timer = useRef<React.MutableRefObject<ReturnType<typeof setTimeout>>>(null);.

It did not help either.

Please advise

答:
Seems like you'r ref can be null or be a number (ReturnType<typeof setTimeout> is number):

```<code>const timer = React.useRef<number | null>(null)
</code>```

Body:
I made a custom Checkbox component to handle events differently, code below:

const DoubleClickCheckbox = ({ filter, handleDoubleClick, handleSingleClick }: DCCheckboxProps) => {
  const delay = 400;
  const timer = useRef(null);

  const classes = useStyles();
  const flags = useFlags();

  useEffect(() => {
    return () => {
      timer.current && clearTimeout(timer.current);
    };
  }, []);

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  const onClick = (e) => {
    if (flags.csRequireFilters) {
      e.stopPropagation();
      handleSingleClick(filter);
      return;
    }

    switch (e.detail) {
      case 1:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        timer.current = setTimeout(() => {
          handleSingleClick(filter);
        }, delay);
        break;
      case 2:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        clearTimeout(timer.current);
        handleDoubleClick(filter);
        break;
      default:
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        clearTimeout(timer.current);
        return;
    }
  };

  return (

 {}} role="button" tabIndex={0}>
      <Checkbox
        label={filter.label}
        className={classes.checkbox_custom}
        checked={filter.selected}
        checkedIcon={filter.mandatory ? <Icons.CheckboxDoubleClick /> : <Icons.CheckboxSingleClick />}
      />

  );
};

I would like to dump my eslint-disable-next-line @typescript-eslint/ban-ts-comment and ts-ignore.

If I rewrite my code it reads as below, I get a typescript error:

  case 1:
    timer.current = setTimeout(() => {
      handleSingleClick(filter);
    }, delay);
    break;

The error is: Type 'Timeout' is not assignable to type 'null'. I have tried various other tricks, for example: const timer = useRef<React.MutableRefObject<ReturnType<typeof setTimeout>>>(null);.

It did not help either.

Please advise

Body:
Seems like you'r ref can be null or be a number (ReturnType<typeof setTimeout> is number):

const timer = React.useRef<number | null>(null)