Reputation: 2613
I have an app based on Android-ViewPagerIndicator.
I would like to create an HorizontalScrollView
in a Fragment
.The view will include some pictures. My problem is that my Scrolling view isn't working beacuse when I'm trying to scroll, I scroll all the fragment and not only the view I want. Hope my question is understandable! :)
This is a part of code:
.xml
<HorizontalScrollView android:id="@+id/horizontalScroll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:fadingEdgeLength="10dp">
<LinearLayout
android:id="@+id/harokLayout"
android:background="#EEEEEE"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app2" android:layout_height="wrap_content" android:layout_width="wrap_content" />
<ImageView android:src="@drawable/app1" android:layout_height="wrap_content" android:layout_width="wrap_content" />
</LinearLayout>
</HorizontalScrollView>
TabPageIndicator:
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* This widget implements the dynamic action bar tab behavior that can change
* across different configurations or circumstances.
*/
public class TabPageIndicator extends HorizontalScrollView implements PageIndicator {
Runnable mTabSelector;
private OnClickListener mTabClickListener = new OnClickListener() {
public void onClick(View view) {
TabView tabView = (TabView)view;
mViewPager.setCurrentItem(tabView.getIndex());
}
};
private LinearLayout mTabLayout;
private ViewPager mViewPager;
private ViewPager.OnPageChangeListener mListener;
private LayoutInflater mInflater;
int mMaxTabWidth;
private int mSelectedTabIndex;
public TabPageIndicator(Context context) {
this(context, null);
}
public TabPageIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
setHorizontalScrollBarEnabled(false);
mInflater = LayoutInflater.from(context);
mTabLayout = new LinearLayout(getContext());
addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.FILL_PARENT));
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
setFillViewport(lockedExpanded);
final int childCount = mTabLayout.getChildCount();
if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
if (childCount > 2) {
mMaxTabWidth = (int)(MeasureSpec.getSize(widthMeasureSpec) ); //edw itan * 0.4f
} else {
mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
}
} else {
mMaxTabWidth = -1;
}
final int oldWidth = getMeasuredWidth();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int newWidth = getMeasuredWidth();
if (lockedExpanded && oldWidth != newWidth) {
// Recenter the tab display if we're at a new (scrollable) size.
setCurrentItem(mSelectedTabIndex);
}
}
private void animateToTab(final int position) {
final View tabView = mTabLayout.getChildAt(position);
if (mTabSelector != null) {
removeCallbacks(mTabSelector);
}
mTabSelector = new Runnable() {
public void run() {
final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
smoothScrollTo(scrollPos, 0);
mTabSelector = null;
}
};
post(mTabSelector);
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (mTabSelector != null) {
// Re-post the selector we saved
post(mTabSelector);
}
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mTabSelector != null) {
removeCallbacks(mTabSelector);
}
}
private void addTab(String text, int index) {
//Workaround for not being able to pass a defStyle on pre-3.0
final TabView tabView = (TabView)mInflater.inflate(R.layout.vpi__tab, null);
tabView.init(this, text, index);
tabView.setFocusable(true);
tabView.setOnClickListener(mTabClickListener);
mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, LayoutParams.FILL_PARENT, 1));
}
@Override
public void onPageScrollStateChanged(int arg0) {
if (mListener != null) {
mListener.onPageScrollStateChanged(arg0);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
if (mListener != null) {
mListener.onPageScrolled(arg0, arg1, arg2);
}
}
@Override
public void onPageSelected(int arg0) {
setCurrentItem(arg0);
if (mListener != null) {
mListener.onPageSelected(arg0);
}
}
@Override
public void setViewPager(ViewPager view) {
final PagerAdapter adapter = view.getAdapter();
if (adapter == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
if (!(adapter instanceof TitleProvider)) {
throw new IllegalStateException("ViewPager adapter must implement TitleProvider to be used with TitlePageIndicator.");
}
mViewPager = view;
view.setOnPageChangeListener(this);
notifyDataSetChanged();
}
public void notifyDataSetChanged() {
mTabLayout.removeAllViews();
TitleProvider adapter = (TitleProvider)mViewPager.getAdapter();
final int count = ((PagerAdapter)adapter).getCount();
for (int i = 0; i < count; i++) {
addTab(adapter.getTitle(i), i);
}
if (mSelectedTabIndex > count) {
mSelectedTabIndex = count - 1;
}
setCurrentItem(mSelectedTabIndex);
requestLayout();
}
@Override
public void setViewPager(ViewPager view, int initialPosition) {
setViewPager(view);
setCurrentItem(initialPosition);
}
@Override
public void setCurrentItem(int item) {
if (mViewPager == null) {
throw new IllegalStateException("ViewPager has not been bound.");
}
mSelectedTabIndex = item;
final int tabCount = mTabLayout.getChildCount();
for (int i = 0; i < tabCount; i++) {
final View child = mTabLayout.getChildAt(i);
final boolean isSelected = (i == item);
child.setSelected(isSelected);
if (isSelected) {
animateToTab(item);
}
}
}
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
mListener = listener;
}
public static class TabView extends LinearLayout {
private TabPageIndicator mParent;
private int mIndex;
public TabView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init(TabPageIndicator parent, String text, int index) {
mParent = parent;
mIndex = index;
TextView textView = (TextView)findViewById(android.R.id.text1);
textView.setText(text);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Re-measure if we went beyond our maximum size.
if (mParent.mMaxTabWidth > 0 && getMeasuredWidth() > mParent.mMaxTabWidth) {
super.onMeasure(MeasureSpec.makeMeasureSpec(mParent.mMaxTabWidth, MeasureSpec.EXACTLY),
heightMeasureSpec);
}
}
public int getIndex() {
return mIndex;
}
}
}
FragmentPagerAdapter2:
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
class FragmentPagerAdapter2 extends FragmentPagerAdapter implements TitleProvider {
private final List<Fragment> fragments;
/**
* @param fm
* @param fragments
*/
public FragmentPagerAdapter2(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/*
* (non-Javadoc)
*
* @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
/*
* (non-Javadoc)
*
* @see android.support.v4.view.PagerAdapter#getCount()
*/
@Override
public int getCount() {
return this.fragments.size();
}
public String getTitle(int position) {
return MarketAppActivity.CONTENT[position % MarketAppActivity.CONTENT.length].toUpperCase();
}
}
Upvotes: 5
Views: 5994
Reputation: 4816
Have you considered using a ViewPager inside your fragment? It seems to be what you're going for as far as the horizontal scrolling/swiping goes, but it's alot less leg work. You basically provide a list of fragments/fragment layouts to your viewpager in your activity, and set your PageAdapter like you normally would. You can either reuse layouts, or create different layouts for each page in your pager. You can check out this blog post for a little more clarity.
http://thepseudocoder.wordpress.com/2011/10/05/android-page-swiping-using-viewpager/
Upvotes: 0
Reputation: 1472
You must create a custom child class of HorizontalScrollView and modify onTouchEvent to intercept the touch event from the fragment if a horizontal swipe is detected.
For example:
public class CustomHorizontalScrollView extends HorizontalScrollView {
...
public void setParent(ViewPager parentView) {
mParentView = parentView;
}
@Override
public synchronized boolean onTouchEvent(MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_DOWN) &&
(mParentView != null)) {
mParentView.requestDisallowInterceptTouchEvent(true);
}
return super.onTouchEvent(event);
}
...
}
mParentView is of course a reference to the ViewPager the fragments are attached to. This way, all further actions associated with that particular MotionEvent (ACTION_MOVE and ACTION_UP) will be given to the child HorizontalScrollView, bypassing the ViewPager altogether.
Upvotes: 1