I'm wondering if there's a more efficient way to handle horizontal scrolling with a good number of images.
Right now I'm using a HorizontalScrollView component with a Frame Layout as its only child. Then I'm laying out the ImageViews on the Layout. It works but I'm noticing that on certain devices the scrolling is very choppy but on others its very smooth.
So I was wondering if there is a better and more efficient way to handle it.
Some code snippets:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/app_background"
tools:context="com.toyota.fanmojis.PostActivity">
<RelativeLayout
android:layout_height="265dp"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:id="@+id/keyboardLayout">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#C9C9C9"
android:layout_alignParentTop="true"
android:id="@+id/shareLayout">
<RelativeLayout
android:id="@+id/socialLayout"
android:layout_centerHorizontal="true"
android:layout_width="217dp"
android:layout_height="40dp">
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/fb_button"
android:layout_marginLeft="8dp"
android:layout_centerVertical="true"
android:background="@drawable/fb_color"
android:scaleType="fitXY"
android:contentDescription="Post via Facebook" />
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/twitter_button"
android:layout_toRightOf="@id/fb_button"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:background="@drawable/twitter_color"
android:scaleType="fitXY"
android:contentDescription="Post via Twitter" />
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/sms_button"
android:layout_toRightOf="@id/twitter_button"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:background="@drawable/sms_color"
android:scaleType="fitXY"
android:contentDescription="Post via SMS" />
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/email_button"
android:layout_toRightOf="@id/sms_button"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:background="@drawable/email_color"
android:scaleType="fitXY"
android:contentDescription="Post via SMS" />
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/copy_paste_button"
android:layout_toRightOf="@id/email_button"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:background="@drawable/copy"
android:scaleType="fitXY"
android:contentDescription="Post via SMS" />
</RelativeLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:text="@string/share"
android:id="@+id/textView"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/socialLayout"
/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/fanmojisLayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/shareLayout">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="32dp"
android:id="@+id/bottomViewLayout"
android:layout_alignParentBottom="true"
android:background="@drawable/red_background">
<ImageButton
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/homeButton"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:background="@drawable/home"
android:scaleType="fitXY"
android:contentDescription="Go back to home" />
<ImageButton
android:layout_width="44dp"
android:layout_height="31dp"
android:id="@+id/backspaceButton"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:background="@drawable/delete_selector"
android:layout_marginRight="1dp"
android:layout_marginLeft="4dp"
android:scaleType="fitXY"
android:contentDescription="Go back to home" />
<Button
android:layout_width="44dp"
android:layout_height="31dp"
android:id="@+id/clearButton"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/backspaceButton"
android:background="@drawable/clear_selector"
android:scaleType="fitXY"
android:contentDescription="Go back to home" />
</RelativeLayout>
<com.upinteractive.fanmojis.components.FanmojiHorizontalScrollView
android:id="@+id/fanmojisScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottomViewLayout"
android:scrollbars="none"
android:animationCache="false"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/fanmojiContentLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</com.upinteractive.fanmojis.components.FanmojiHorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
<com.upinteractive.fanmojis.components.ChatBubble
android:id="@+id/chatBubble"
android:layout_width="220dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:background="@drawable/chat"/>
<RelativeLayout
android:id="@+id/errorLayout"
android:layout_width="300dp"
android:layout_height="180dp"
android:layout_marginTop="80dp"
android:layout_centerHorizontal="true"
android:background="@drawable/error_layout_bg"
android:visibility="invisible">
<TextView
android:id="@+id/errorText"
android:textColor="@android:color/white"
android:textAlignment="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
And the code that loads the frame layout with the images:
protected void setupScroll() {
double hspacing = (displaymetrics.widthPixels - (IMAGE_SIZE * 6)) / 7;
double hfixedspacing = hspacing;
double vspacing = 5.0;
double max = 0;
double topSpacing = 20.0;
double xPosition = hspacing;
double yPosition = topSpacing;
int row = 0;
int col = 0;
int viewcount = imageArray.length() / 18;
int mod = (imageArray.length() % 18);
if (mod > 6)
viewcount++;
FrameLayout fl = (FrameLayout) this.findViewById(R.id.fanmojiContentLayout);
fl.setBackgroundColor(getResources().getColor(R.color.kb_bg_color));
scrollView.setBackgroundColor(getResources().getColor(R.color.kb_bg_color));
int inSampleSize = 0;
try {
for (int i = 0; i < imageArray.length(); i++) {
JSONObject emoji = imageArray.getJSONObject(i);
String basename = emoji.getString("name");
String fullname = "f" + basename + "_small";
int resourceID = getResources().getIdentifier(fullname, "drawable", getPackageName());
if(i == 0){
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), resourceID, options);
inSampleSize = Util.calculateInSampleSize(options,IMAGE_SIZE,IMAGE_SIZE);
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;
Bitmap b = BitmapFactory.decodeResource(getResources(), resourceID, options);
FMImageView iv = new FMImageView(this);
iv.name = basename;
iv.fullname = fullname;
iv.setImageBitmap(b);
FrameLayout.LayoutParams imageParams = new FrameLayout.LayoutParams(IMAGE_SIZE, IMAGE_SIZE);
imageParams.leftMargin = (int) xPosition;
imageParams.topMargin = (int) yPosition;
fl.addView(iv, imageParams);
col++;
if (col > 5) {
col = 0;
row++;
if (row > 2) {
xPosition += hspacing + IMAGE_SIZE;
hfixedspacing = xPosition;
} else {
xPosition = hfixedspacing;
}
yPosition += vspacing + IMAGE_SIZE;
} else {
xPosition += hspacing + IMAGE_SIZE;
}
if (xPosition > max)
max = xPosition;
if (row > 2) {
xPosition = hfixedspacing;
yPosition = topSpacing;
row = 0;
col = 0;
}
}
} catch (JSONException je) {
je.printStackTrace();
}
fl.setMinimumWidth((int) max + 200);
}
You would probably get better performance with a scrolling component that recycles its views.
Try using a RecyclerView
with a GridLayoutManager
that has the orientation
property set to "horizontal".
You'll need to code an adapter for the RecyclerView
.