I implemented a GridView
inside PageViewer
, but scrolling is not as smooth as it should be. Views inside GridView
are intercepting touches.
This is driving me crazy I have tried everything and while one thing worked it is not good solution in the end. First here is my code.
apps_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView
android:id="@+id/appGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ic_launcher_background"
android:horizontalSpacing="4dp"
android:numColumns="4"
android:paddingTop="10dp"
android:stretchMode="columnWidth"
android:verticalSpacing="15dp"/>
</LinearLayout>
app_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:gravity="center"
android:paddingEnd="15dp"
android:paddingStart="15dp"
android:singleLine="true"
android:text="title"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
activity_main.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="45dp"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
AppModel.java
public class AppModel {
private String label;
private String pkg;
private Drawable mIcon;
public AppModel(String name, String pkg, Drawable icon) {
this.label = name;
this.pkg = pkg;
this.mIcon = icon;
}
public AppModel(String name) {
this.label = name;
}
public String getLabel() {
return this.label;
}
public String getPkg() {
return this.pkg;
}
public Drawable getIcon() {
return mIcon;
}
}
AppListAdapter.java
public class AppListAdapter extends BaseAdapter {
private ArrayList<AppModel> apps;
private LayoutInflater layoutInflater;
public AppListAdapter(Context context, ArrayList<AppModel> apps) {
this.apps = apps;
this.layoutInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return apps.size();
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public Object getItem(int position) {
AppModel app = apps.get(position);
if(app == null) {
return null;
}
return app;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
AppModel app = apps.get(position);
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.app_item, null);
}
if(app == null) {
return convertView;
}
((TextView)convertView.findViewById(R.id.text)).setText(app.getLabel());
return convertView;
}
}
TestPagerAdapter.java
public class TestPagerAdapter extends PagerAdapter {
private Context mContext;
private LayoutInflater inflater;
private ArrayList<AppModel> apps;
private int perPage = 12;
public TestPagerAdapter(Context context) {
this.mContext = context;
this.inflater = LayoutInflater.from(context);
}
@Override
public Object instantiateItem(ViewGroup parent, int position) {
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.apps_grid, parent, false);
ArrayList<AppModel> pageApps = getAppsForPage(position);
if(pageApps == null) {
return layout;
}
final GridView appGrid = (GridView) layout.findViewById(R.id.appGrid);
final AppListAdapter gridAdapter = new AppListAdapter(mContext, pageApps);
appGrid.setVerticalScrollBarEnabled(false);
appGrid.setAdapter(gridAdapter);
parent.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup parent, int position, Object view) {
parent.removeView((View) view);
}
@Override
public int getCount() {
if(apps != null) {
return (int) Math.ceil((double) apps.size() / perPage);
} else {
return 0;
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
public void setData(ArrayList<AppModel> data) {
if(data != null) {
this.apps = data;
}
}
public ArrayList<AppModel> getAppsForPage(int page) {
if(apps == null) {
return null;
}
int size = apps.size();
int offset = getOffset(page);
ArrayList<AppModel> pageApps = new ArrayList<AppModel>(size);
for(int i = 0; i < perPage; i++) {
if(offset+i < size) {
pageApps.add(apps.get(offset+i));
}
}
return pageApps;
}
public int getOffset(int page) {
return perPage*page;
}
}
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
TestPagerAdapter mPAdapter = new TestPagerAdapter(this);
viewPager.setAdapter(mPAdapter);
ArrayList<AppModel> items = new ArrayList<AppModel>(20);
for(int i=0;i<20;i++) {
AppModel app = new AppModel(""+i);
items.add(app);
}
mPAdapter.setData(items);
mPAdapter.notifyDataSetChanged();
}
So, here is what I tried:
I replaced GridView
with RecyclerView
.
Added all this attributes on EVERY View
android:clickable="false"
android:contextClickable="false"
android:defaultFocusHighlightEnabled="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:focusedByDefault="false"
android:isScrollContainer="false"
android:longClickable="false"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
android:touchscreenBlocksFocus="false"
Overriding OnTouchListener (and many other) on GridView
and returning true
.
probably tried some other things that I cannot remember right now.
The only thing that worked was settings android:filterTouchesWhenObscured="true"
attribute on GridView
while some other applications view was on top (so condition "WhenObscured" was satisfied)
When I tried this my ViewPager
started scrolling very smoothly, in other cases it sometimes does not scroll (probably when GridView
intercepts it).
Note that items inside GridView
in the end must be clickable.
UPDATE
https://github.com/mpa4hu/GridViewPager this is a github link to the project, to simulate the problem scroll forward and backward with gesture similar to this picture
GridView
, it is not really an error – Piranesi