List view grid or 2 list views better?
I tried to get a combo box view in my activity, but I got an error.
Is there any other way to get the result below?
In my main activity, I want one list view to display a large image and the second to display them as 2 images per line, should I use a grid view or is the second list view enough?
this is my code
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="sssss"
android:textSize="16sp"
android:padding="10dp"
android:background="#ffe474" />
<ListView
android:id="@+id/list3"
android:layout_width="wrap_content"
android:layout_height="1500dp"
android:background="#eeeeee" >
</ListView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="Recommanded"
android:textSize="18sp"
android:padding="10dp"
android:background="#ffe474" />
<ListView
android:id="@+id/list1"
android:layout_width="wrap_content"
android:layout_height="1500dp"
android:background="#eeeeee" >
</ListView>
</LinearLayout>
</ScrollView>
source to share
This is a bit tricky thing. Whenever we get such a requirement, we have to do a workaround like keeping the LinearLayout with orientation as vertical and keep the LinearLayout inside the ScrollView . I created a sample for your problem. Hope this helps you.
custom_grid_item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_horizontal"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black">
<LinearLayout
android:id="@+id/gridItemLeft"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:layout_margin="4dp"
android:gravity="left"
android:visibility="invisible">
<TextView
android:id="@+id/itemNameLeft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Medium"
android:text="@string/app_name"
android:textColor="@android:color/black"
android:padding="4dp"
android:background="@android:color/white"/>
</LinearLayout>
<LinearLayout
android:id="@+id/gridItemRight"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:layout_margin="4dp"
android:gravity="right"
android:visibility="invisible">
<TextView
android:id="@+id/itemNameRight"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:textAppearance="@android:style/TextAppearance.Medium"
android:text="@string/app_name"
android:textColor="@android:color/black"
android:background="@android:color/white"/>
</LinearLayout>
</LinearLayout>
custom_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:background="@android:color/black">
<TextView
android:id="@+id/itemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Medium"
android:background="@android:color/white"
android:padding="8dp"
android:text="@string/app_name"
android:textColor="@android:color/black"/>
</LinearLayout>
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:id="@+id/custom_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"/>
<LinearLayout
android:orientation="vertical"
android:id="@+id/custom_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
MyActivity.java:
public class MyActivity extends Activity {
private List<String> mItems;
private LinearLayout mListLayout, mGridLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mItems = new ArrayList<String>(Arrays.asList("Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10"));
mListLayout = (LinearLayout) findViewById(R.id.custom_list);
mGridLayout = (LinearLayout) findViewById(R.id.custom_grid);
loadListView();
loadGridView();
}
private void loadGridView() {
if (mItems.size() % 2 == 0) {
loadEvenGridView(true);
} else {
loadEvenGridView(false);
LayoutInflater inflater = getLayoutInflater();
LinearLayout gridItem = (LinearLayout) inflater.inflate(R.layout.custom_grid_item, null);
LinearLayout leftItem = (LinearLayout) gridItem.findViewById(R.id.gridItemLeft);
LinearLayout rightItem = (LinearLayout) gridItem.findViewById(R.id.gridItemRight);
leftItem.setVisibility(View.VISIBLE);
rightItem.setVisibility(View.INVISIBLE);
TextView txtItemName = (TextView) gridItem.findViewById(R.id.itemNameLeft);
txtItemName.setText(mItems.get(mItems.size() - 1));
leftItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), mItems.get(mItems.size() - 1), Toast.LENGTH_SHORT).show();
}
});
mGridLayout.addView(gridItem);
}
}
private void loadEvenGridView(boolean isEvenSize) {
int len = mItems.size();
if (!isEvenSize) {
len = len - 1;
}
if (len > 1) {
for (int index = 1; index < len; index += 2) {
LayoutInflater inflater = getLayoutInflater();
LinearLayout gridItem = (LinearLayout) inflater.inflate(R.layout.custom_grid_item, null);
LinearLayout leftItem = (LinearLayout) gridItem.findViewById(R.id.gridItemLeft);
LinearLayout rightItem = (LinearLayout) gridItem.findViewById(R.id.gridItemRight);
TextView txtItemName;
for (int sIndex = 0; sIndex < 2; sIndex++) {
switch (sIndex) {
case 0:
leftItem.setVisibility(View.VISIBLE);
txtItemName = (TextView) gridItem.findViewById(R.id.itemNameLeft);
txtItemName.setText(mItems.get(index - 1));
final int finalIndex = index;
leftItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), mItems.get(finalIndex - 1), Toast.LENGTH_SHORT).show();
}
});
continue;
case 1:
rightItem.setVisibility(View.VISIBLE);
txtItemName = (TextView) gridItem.findViewById(R.id.itemNameRight);
txtItemName.setText(mItems.get(index));
final int finalIndex1 = index;
rightItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), mItems.get(finalIndex1), Toast.LENGTH_SHORT).show();
}
});
continue;
}
}
mGridLayout.addView(gridItem);
}
}
}
private void loadListView() {
for (int index = 0; index < mItems.size(); index++) {
LayoutInflater inflater = getLayoutInflater();
View listItem = inflater.inflate(R.layout.custom_list_item, null);
TextView txtItemName = (TextView) listItem.findViewById(R.id.itemName);
txtItemName.setText(mItems.get(index));
mListLayout.addView(listItem);
final int finalIndex = index;
listItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), mItems.get(finalIndex), Toast.LENGTH_SHORT).show();
}
});
}
}
}
Screenshot:
source to share
A more suitable and simpler solution would be to use a RecyclerView with a GridLayoutManager. The GridLayoutManager takes a SpanSizeLookup object that lets you specify how many spacing each of the elements will take.
The complete solution to this problem includes the following parts:
Activity with RecyclerView, GridLayoutManager and custom SpanSizeLookup
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
// specify that grid will consist of 2 columns
GridLayoutManager gridLayoutManager = new GridLayoutManager(getApplicationContext(), 2);
// provide our CustomSpanSizeLookup which determines how many spans each item in grid will occupy
gridLayoutManager.setSpanSizeLookup(new CustomSpanSizeLookup());
// provide our GridLayoutManager to the view
recyclerView.setLayoutManager(gridLayoutManager);
// this is fake list of images
List<Integer> imageResList = getMockedImageList();
// finally, provide adapter to the recycler view
Adapter adapter = new Adapter(imageResList);
recyclerView.setAdapter(adapter);
}
private List<Integer> getMockedImageList() {
// fake images list, you'd need to upload your own image resources
List<Integer> imageResList = new ArrayList<Integer>();
imageResList.add(R.drawable.img1);
imageResList.add(R.drawable.img2);
imageResList.add(R.drawable.img3);
imageResList.add(R.drawable.img4);
imageResList.add(R.drawable.img5);
imageResList.add(R.drawable.img6);
return imageResList;
}
private static class CustomSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int i) {
if(i == 0 || i == 1) {
// grid items on positions 0 and 1 will occupy 2 spans of the grid
return 2;
} else {
// the rest of the items will behave normally and occupy only 1 span
return 1;
}
}
}
}
RecyclerView adapter
public class Adapter extends RecyclerView.Adapter {
// I assume that you will pass images as list of resources, but this can be easily switched to a list of URLS
private List<Integer> imageResList = new ArrayList<Integer>();
public Adapter(List<Integer> imageUrlList) {
this.imageResList = imageUrlList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycle_view_item, viewGroup, false);
return new ItemViewHolder(itemView);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
ItemViewHolder itemViewHolder = (ItemViewHolder) viewHolder;
itemViewHolder.item.setImageResource(imageResList.get(i));
}
@Override
public int getItemCount() {
return imageResList.size();
}
private static class ItemViewHolder extends RecyclerView.ViewHolder {
private ImageView item;
public ItemViewHolder(View itemView) {
super(itemView);
this.item = (ImageView) itemView.findViewById(R.id.item_image);
}
}
}
activity_main.xml layout
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
recycler_view_item.xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="150dp"
android:padding="10dp">
<ImageView
android:id="@+id/item_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
</LinearLayout>
And the last snippet would be to add a dependency in the build.gradle file for the RecyclerView:
dependencies {
compile 'com.android.support:recyclerview-v7:21.0.+'
}
And here's the result:
The advantages of this solution are as follows:
- it is scalable, lightweight and highly customizable
- it is efficient when it recycles views when scrolling up and down
- no need to fiddle with touch events, which can easily become very complex to handle after adding additional touch functionality.
I hope this is helpful.
source to share
There is a fairly simple way to implement this: - AsymmetricGridView
Hope this helps you!
source to share
You can't just scroll View
inside another scrollable View
and expect them to work out of the box, especially if they both scroll in the same direction. The best way to make this possible is to extend these Views and intercept the sensory events that are sent to them. Here you can define the user-generated scroll direction and route the touch event accordingly.
Read the following: Intercept Touch Events in a ViewGroup
source to share