I need to add a swipe view in tab activity.In these below xml coding
I just created a six tabs namely home,blog,audio,video,more and
gallery.
The Tabs are created perfectly.But I cannot able to know how to add a swipe for that six tabs.I need
to add a right to left swipe and left to right swipe.
layout_home.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TabHost
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#drawable/bottom_bar"
android:layout_weight="0" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/tab_home"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:id="#+id/tab_video"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:id="#+id/tab_audio"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
<FrameLayout
android:id="#+id/tab_blog"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
<FrameLayout
android:id="#+id/tab_gal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
<FrameLayout
android:id="#+id/tab_more"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</FrameLayout>
<com.sit.gems.util.AppPromoPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0" />
</LinearLayout>
</TabHost>
</LinearLayout>
AppPromoPager.java:
These is the AppPromopager.Here I am using the ViewPager.
package com.sit.gems.util;
import java.net.URLDecoder;
import java.util.List;
import android.content.Context;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;
import com.gems.android.R;
import com.sit.gems.app.AppData;
import com.sit.gems.util.ImageCache.ImageCacheParams;
public class AppPromoPager extends RelativeLayout implements
ViewPager.OnPageChangeListener {
//private PromoPageIndicator indicator;
private PromoPagerListener listener;
private Handler trackerHandler = new Handler();
private ImageFetcher mImageFetcher;
public AppPromoPager(Context context) {
super(context);
}
public AppPromoPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AppPromoPager(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void init(FragmentActivity context, List<String> promotions) {
ImageCacheParams cacheParams = new ImageCacheParams(context, AppConstants.IMAGE_CACHE_DIR);
mImageFetcher = new ImageFetcher(context, AppData.getScreenWidth(),(AppData.getScreenWidth()/2));
mImageFetcher.setLoadingImage(R.drawable.ic_launcher);
mImageFetcher.addImageCache(context.getSupportFragmentManager(), cacheParams);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
ViewPager pager = new ViewPager(context);
ViewPagerAdapter adapter = new ViewPagerAdapter(context, promotions);
pager.setAdapter(adapter);
pager.setCurrentItem(0);
pager.setOnPageChangeListener(this);
addView(pager, params);
//indicator = new PromoPageIndicator(context);
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params1.addRule(RelativeLayout.CENTER_HORIZONTAL);
params1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params1.setMargins(0, 0, 0, 3);
//addView(indicator, params1);
//if (promotions.size() > 1)
// indicator.addCircleImage(promotions.size());
/*pager.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE
&& scrollView != null) {
scrollView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
});*/
}
class ViewPagerAdapter extends PagerAdapter {
Context activity;
List<String> promotions;
public ViewPagerAdapter(Context context, List<String> promotions) {
this.promotions = promotions;
activity = context;
}
public int getCount() {
return promotions.size();
}
public Object instantiateItem(View collection, final int position) {
final ImageView view = new ImageView(activity);
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
view.setScaleType(ScaleType.CENTER);
String imageUrl = promotions.get(position);
if (imageUrl != null && imageUrl.length() > 0) {
setImage(view, imageUrl);
}
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.selectedPromo(promotions.get(position),position);
}
});
((ViewPager) collection).addView(view, 0);
return view;
}
#Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
#Override
public Parcelable saveState() {
return null;
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
//listener.selectedPosition(arg0);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
listener.selectedPosition(position);
}
public interface PromoPagerListener {
public void selectedPromo(String offer,int postion);
public void selectedPosition(int postion);
}
public void setPromoPagerListener(PromoPagerListener listener) {
this.listener = listener;
}
private void setImage(final ImageView view, final String imageUrl) {
trackerHandler.post(new Runnable() {
#Override
public void run() {
mImageFetcher.loadImage(URLDecoder.decode(imageUrl),view);
}
});
}
}
I thought with the help of viewpager I can able to get a Swipe view.
ViewPager was added in AppPromoPager.
I added an AppPromoPager to that
layout_home.xml file.But till now I didn't get a swipe view.Anybody can help me with these.Thank you.
Better to use the Scrollable Tabs which uses a combination of Swipe view pager with the action bar tabs.
What I did is in each tabcontent, implement the swipe listener. In the tabhost, implement a swipe method.
tabcontent
layout.setOnTouchListener(new OnTouchListener() {
private PointerCoords mDownPos = new PointerCoords();
private PointerCoords mUpPos = new PointerCoords();
#Override
public boolean onTouch(View arg0, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
event.getPointerCoords(0, mDownPos);
return true;
}
case MotionEvent.ACTION_UP: {
event.getPointerCoords(0, mUpPos);
float dx = mDownPos.x - mUpPos.x;
// Check for horizontal wipe
if (Math.abs(dx) > SWIPE_MIN_DISTANCE) {
if (dx > 0) {
mParent.swipe(DIRECTION_RIGHT);
} else {
mParent.swipe(DIRECTION_LEFT);
}
return true;
}
}
}
return false;
}
});
protected void swipe(int direction) {
int current = mTabHost.getCurrentTab();
if (direction == DIRECTION_LEFT) {
int newTab = --current % mTabHost.getTabWidget().getTabCount();
mTabHost.setCurrentTab( (newTab < 0) ? mTabHost.getTabWidget().getTabCount()-1 : newTab);
}
else {
mTabHost.setCurrentTab(++current % mTabHost.getTabWidget().getTabCount());
}
}
hey you should do this by actionBar tabs + viewpager here is a tutorial which let you make what you want.
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
Related
Want to create the view pager same as following UI, applied custom transformer but not working.
ViewPager.java
public class MyViewPager extends ViewPager implements ViewPager.PageTransformer {
public static final String TAG = "MyViewPager";
private float MAX_SCALE = 0.0f;
private int mPageMargin;
private boolean animationEnabled=true;
private boolean fadeEnabled=false;
private float fadeFactor=0.5f;
public MyViewPager(Context context) {
this(context, null);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// clipping should be off on the pager for its children so that they can scale out of bounds.
setClipChildren(false);
setClipToPadding(false);
// to avoid fade effect at the end of the page
setOverScrollMode(2);
setPageTransformer(false, this);
setOffscreenPageLimit(3);
mPageMargin = dp2px(context.getResources(), 50);
setPadding(mPageMargin, mPageMargin, mPageMargin, mPageMargin);
}
public int dp2px(Resources resource, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resource.getDisplayMetrics());
}
public void setAnimationEnabled(boolean enable) {
this.animationEnabled = enable;
}
public void setFadeEnabled(boolean fadeEnabled) {
this.fadeEnabled = fadeEnabled;
}
public void setFadeFactor(float fadeFactor) {
this.fadeFactor = fadeFactor;
}
#Override
public void setPageMargin(int marginPixels) {
mPageMargin = marginPixels;
// setPadding(mPageMargin, mPageMargin, mPageMargin, mPageMargin);
}
#Override
public void transformPage(View page, float position) {
if (mPageMargin <= 0|| !animationEnabled)
return;
page.setPadding(mPageMargin / 3, mPageMargin / 3, mPageMargin / 3, mPageMargin / 3);
if (MAX_SCALE == 0.0f && position > 0.0f && position < 1.0f) {
MAX_SCALE = position;
}
position = position - MAX_SCALE;
float absolutePosition = Math.abs(position);
if (position <= -1.0f || position >= 1.0f) {
if(fadeEnabled)
page.setAlpha(fadeFactor);
// Page is not visible -- stop any running animations
} else if (position == 0.0f) {
// Page is selected -- reset any views if necessary
page.setScaleX((1 + MAX_SCALE));
page.setScaleY((1 + MAX_SCALE));
page.setAlpha(1);
} else {
page.setScaleX(1 + MAX_SCALE * (1 - absolutePosition));
page.setScaleY(1 + MAX_SCALE * (1 - absolutePosition));
if(fadeEnabled)
page.setAlpha( Math.max(fadeFactor, 1 - absolutePosition));
}
}
}
UPDATE - if you want to make current page zoom use below PageTransformer
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
public class JavaActivity extends AppCompatActivity {
ViewPager2 myViewPager2;
MyAdapter MyAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
myViewPager2 = findViewById(R.id.viewpager);
MyAdapter = new MyAdapter(this);
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
myViewPager2.setAdapter(MyAdapter);
myViewPager2.setOffscreenPageLimit(3);
float pageMargin = getResources().getDimensionPixelOffset(R.dimen.pageMargin);
float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
myViewPager2.setPageTransformer((page, position) -> {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (position < -1) {
page.setTranslationX(-myOffset);
} else if (position <= 1) {
float scaleFactor = Math.max(0.7f, 1 - Math.abs(position - 0.14285715f));
page.setTranslationX(myOffset);
page.setScaleY(scaleFactor);
page.setAlpha(scaleFactor);
} else {
page.setAlpha(0);
page.setTranslationX(myOffset);
}
});
}
}
OUTPUT
NOTE: you can download complete code from my GitHub repositories
Try this way
JavaActivity
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import androidx.viewpager2.widget.ViewPager2;
public class JavaActivity extends AppCompatActivity {
ViewPager2 myViewPager2;
MyAdapter MyAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);
myViewPager2 = findViewById(R.id.viewpager);
MyAdapter = new MyAdapter(this);
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
myViewPager2.setAdapter(MyAdapter);
myViewPager2.setOffscreenPageLimit(3);
float pageMargin= getResources().getDimensionPixelOffset(R.dimen.pageMargin);
float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
myViewPager2.setPageTransformer(new ViewPager2.PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (myViewPager2.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
if (ViewCompat.getLayoutDirection(myViewPager2) == ViewCompat.LAYOUT_DIRECTION_RTL) {
page.setTranslationX(-myOffset);
} else {
page.setTranslationX(myOffset);
}
} else {
page.setTranslationY(myOffset);
}
}
});
}
}
activity_java layout file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".JavaActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewpager"
android:clipToPadding="false"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
>
MyAdapter
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
public MyAdapter(Context context) {
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_item, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.tvName.setText(String.format("Row number%d", position));
if (position % 2 ==0){
holder.imgBanner.setBackgroundColor(Color.RED);
}else {
holder.imgBanner.setBackgroundColor(Color.GREEN);
}
}
#Override
public int getItemCount() {
return 15;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
ImageView imgBanner;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
imgBanner = itemView.findViewById(R.id.imgBanner);
}
}
}
row_item layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_marginLeft="#dimen/pageMarginAndOffset"
android:layout_marginRight="#dimen/pageMarginAndOffset"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/imgBanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorAccent"
android:contentDescription="#string/app_name"/>
<TextView
android:id="#+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_centerInParent="true"
android:textColor="#android:color/white"
android:textSize="20sp"
android:textStyle="bold"
tools:text="Hello"/>
</RelativeLayout>
OUTPUT
Using ViewPager2 (that has RecyclerView in it).
vp2 is instance of ViewPager2
This worked for me:
RecyclerView rv = (RecyclerView) vp2.getChildAt(0);
rv.setPadding(80, 0, 80, 0);
rv.setClipToPadding(false);
I used FragmentStateAdapter for it and overriding getItemId() and containsItem() for add/remove fragments.
result is here:
You can make use of clipToPadding and programmatically adding the pageMargin and padding to your viewpager.
Try something like this-
viewpager.setClipToPadding(false);
viewpager.setPadding(40, 0, 70, 0);
viewpager.setPageMargin(20);
I'm trying to figure out why my images within class CustomPagerAdapter mResources are NOT showing up once the VerticalViewPager widget appears -- nothing on start and nothing during vertical swipe.
I've been at it for a couple days but just cant crack it. Doesnt help the documentation on ViewPager / Adapters isnt very clear.
Using - Nexus 6 AVD, minSdkVersion = 19
When i attempt to scroll up (single click from the bottom and swipe up all the way to the top) i then receive this error message...
*AndroidRuntime: FATAL EXCEPTION: main
Process: sparktic.com.verticalviewpager, PID: 19242
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3562)*
AFAIK i'm adding and removing pager_item correctly.
java/ MainActivity.java
package sparktic.com.verticalviewpager;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity
{
VerticalViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = findViewById(R.id.viewpager);
CustomPagerAdapter adapter = new CustomPagerAdapter(this);
mPager.setAdapter(adapter);
}
class CustomPagerAdapter extends PagerAdapter
{
Context mContext;
public LayoutInflater mLayoutInflater;
int[] mResources = {
R.drawable.first, // Dload: https://i.imgur.com/suvAa9x.jpg
R.drawable.second, // Dload: https://i.imgur.com/c2f0Hvy.jpg
R.drawable.third // Dload: https://i.imgur.com/0GAs8qp.jpg
};
public CustomPagerAdapter(Context context)
{
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount()
{
return mResources.length;
}
#Override
public boolean isViewFromObject(View view, Object object)
{
return view == ((LinearLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position)
{
View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
imageView.setImageResource(mResources[position]);
container.addView(imageView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView((LinearLayout) object);
}
}
}
layout/ activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="sparktic.com.verticalviewpager.MainActivity">
<sparktic.com.verticalviewpager.VerticalViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
layout/ pager_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="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageView" />
</LinearLayout>
java/ VerticalViewPager.java
package sparktic.com.verticalviewpager;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class VerticalViewPager extends ViewPager
{
public VerticalViewPager(Context context)
{
this(context, null);
}
public VerticalViewPager(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
#Override
public boolean canScrollHorizontally(int direction)
{
return false;
}
#Override
public boolean canScrollVertically(int direction)
{
return super.canScrollHorizontally(direction);
}
private void init()
{
setPageTransformer(true, new VerticalPageTransformer());
setOverScrollMode(View.OVER_SCROLL_NEVER);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
final boolean toIntercept = super.onInterceptTouchEvent(flipXY(ev));
flipXY(ev);
return toIntercept;
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
final boolean toHandle = super.onTouchEvent(flipXY(ev));
flipXY(ev);
return toHandle;
}
private MotionEvent flipXY(MotionEvent ev)
{
final float width = getWidth();
final float height = getHeight();
final float x = (ev.getY() / height) * width;
final float y = (ev.getX() / width) * height;
ev.setLocation(x, y);
return ev;
}
private static final class VerticalPageTransformer implements ViewPager.PageTransformer
{
#Override
public void transformPage(View view, float position)
{
final int pageWidth = view.getWidth();
final int pageHeight = view.getHeight();
if (position < -1)
{
view.setAlpha(0);
}
else if (position <= 1)
{
view.setAlpha(1);
view.setTranslationX(pageWidth * -position);
float yPosition = position * pageHeight;
view.setTranslationY(yPosition);
}
else
{
view.setAlpha(0);
}
}
}
}
Solved my own problem. In case it helps someone else...
the issue was within "instantiateItem" method.
container.addView(imageView); should have been container.addView(itemView);
I still dont have a solid grasp as to what is happening within the PageAdapter overrides but it works so i'll take the win and move on.
My Issue is that I have a LinearLayout that I am inflating at runtime to a LinearLayout inside ScrollView.
This is the main_activity.xml
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/controlLayoutCV"
android:layout_alignParentStart="true"
android:layout_below="#+id/toolLayoutCV">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="#dimen/dp5"
android:paddingLeft="#dimen/dp7"
android:paddingRight="#dimen/dp7"
android:paddingTop="#dimen/dp5">
<android.support.v7.widget.CardView
android:id="#+id/questionQuizCV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="#dimen/dp2">
<com.emedicoz.app.CustomViews.JustifiedTextView
android:id="#+id/questionQuizTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/dp5"
android:text="" />
</android.support.v7.widget.CardView>
<LinearLayout
android:id="#+id/quizQuestionLL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/questionQuizCV"
android:layout_marginTop="#dimen/dp5"
android:orientation="vertical"
android:padding="#dimen/dp5" />
</RelativeLayout>
</ScrollView>
& this is the item_layout.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mcqlayout_LL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/dp5"
android:minHeight="30dp"
android:orientation="horizontal"
android:paddingBottom="#dimen/dp7"
android:paddingTop="#dimen/dp7">
<TextView
android:id="#+id/optioniconTV"
android:layout_width="#dimen/dp40"
android:layout_height="#dimen/dp40"
android:background="#drawable/circle_bg"
android:gravity="center"
android:padding="#dimen/dp3"
android:text="A"
android:textSize="#dimen/sub_heading_text_size" />
<com.emedicoz.app.CustomViews.JustifiedTextView
android:id="#+id/optionTextTV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="#dimen/dp10" />
</LinearLayout>
This is the CustomTextView that I have created to show the HTML content directly. The JustifiedTextView.class is
public class JustifiedTextView extends WebView {
private String text = "";
private int textSize = 12;
private int backgroundColor = Color.TRANSPARENT;
public JustifiedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWebChromeClient(new WebChromeClient() {});
}
public void setText(String s) {
this.text = s;
reloadData();
}
#SuppressLint("NewApi")
private void reloadData() {
// loadData(...) has a bug showing utf-8 correctly. That's why we need to set it first.
this.getSettings().setDefaultTextEncodingName("utf-8");
// this.loadData(String.format(core,textColor,textSize,text), "text/html","utf-8");
this.loadData(text, "text/html", "utf-8");
// set WebView's background color *after* data was loaded.
super.setBackgroundColor(backgroundColor);
// Hardware rendering breaks background color to work as expected.
// Need to use software renderer in that case.
if (android.os.Build.VERSION.SDK_INT >= 11)
this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
public void setTextSize(int textSize) {
this.textSize = textSize;
reloadData();
}
}
I have tried All of the solutions mentioned below.
Disable WebView touch events in Android
Already tried to set the android:descendantFocusability="blocksDescendants" to ScrollView
Why the click Event of LinearLayout does not fire when making click on WebView?
This is the way I am inflating the Layout and handle the click event.
private LinearLayout initAnswerMCViews(String text, String questions, Questions questionsModel) {
LinearLayout view = (LinearLayout) View.inflate(activity, R.layout.mcq_quiz, null);
answerTV = (JustifiedTextView) view.findViewById(R.id.optionTextTV);
optionIconTV = (TextView) view.findViewById(R.id.optioniconTV);
mcqItemLL = (LinearLayout) view.findViewById(R.id.mcqlayout_LL);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
lp.setMargins(3, 3, 3, 3);
mcqItemLL.setLayoutParams(lp);
if (questionsModel.isAnswered()) {
String[] answer = questionsModel.getUser_answer().split(",");
for (int i = 0; i < answer.length; i++) {
if (answer[i].equals(text)) {
answerTV.setText(questions);
optionIconTV.setText(text);
optionIconTV.setBackgroundResource(R.drawable.circle_bg_true);
} else {
answerTV.setText(questions);
optionIconTV.setText(text);
}
}
} else {
answerTV.setText(questions);
optionIconTV.setText(text);
}
mcqItemLL.setTag(R.id.questions, optionIconTV.getText().toString());
mcqItemLL.setTag(R.id.optionsAns, mcqItemLL);
mcqItemLL.setOnClickListener(optionClickListener);
viewArrayList.add(mcqItemLL);
return view;
}
Why the click is not get listen when clicked on the WebView part in the Layout?
I finally found the issue.
It is basically the issue of conflicting Touch Event of both parent Scrollview and CustomWebView.
So, by using the new classes that itself overriding the ClickListener and TouchListener.
package com.app.CustomViews;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
public class TestSeriesOptionWebView extends WebView implements GestureDetector.OnGestureListener {
private boolean check = false;
class LongClick implements OnLongClickListener {
final /* synthetic */ TestSeriesOptionWebView testSeriesOptionWebView;
LongClick(TestSeriesOptionWebView testSeriesOptionWebView) {
this.testSeriesOptionWebView = testSeriesOptionWebView;
}
public boolean onLongClick(View view) {
return true;
}
}
public TestSeriesOptionWebView(Context context) {
super(context);
handleClick();
}
public TestSeriesOptionWebView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
handleClick();
}
public TestSeriesOptionWebView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
handleClick();
}
private void handleClick() {
setFocusable(false);
/*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}*/
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setVerticalScrollBarEnabled(false);
setBackgroundColor(0);
setHapticFeedbackEnabled(false);
setOnLongClickListener(new LongClick(this));
}
public void setDisableWebViewTouchListener(boolean z) {
this.check = z;
}
public boolean onTouchEvent(MotionEvent motionEvent) {
if (this.check) {
return false;
}
return super.onTouchEvent(motionEvent);
}
public boolean canScrollHorizontal(int i) {
int computeHorizontalScrollOffset = computeHorizontalScrollOffset();
int computeHorizontalScrollRange = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
if (computeHorizontalScrollRange == 0) {
return false;
}
if (i < 0) {
if (computeHorizontalScrollOffset <= 0) {
return false;
}
return true;
} else if (computeHorizontalScrollOffset >= computeHorizontalScrollRange - 1) {
return false;
} else {
return true;
}
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
public boolean onDown(MotionEvent motionEvent) {
return true;
}
public void onShowPress(MotionEvent motionEvent) {
}
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
return f != 0.0f;
}
public void onLongPress(MotionEvent motionEvent) {
}
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
return true;
}
}
If anybody faces this type of issue, then Use this Custom Class TestSeriesOptionWebView.class.
I got swipe up and swipe down for a layout by using setOnTouchListener (For understanding see below images)
Images
But i want to swipe up and swipe down the layout when clicking on the button not when OnTouchListener. For this i tried almost all examples in the online but i didn't get any solution according to my requirement. So, please help me to make OnTouchListener event when clicking on the button
My Code
Activity
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.RelativeLayout;
public class SwipeUpActivity extends Activity {
RelativeLayout rlSwipeHolder, rlSwipe1, rlSwipe2;
private float startY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe_up);
rlSwipeHolder = (RelativeLayout) findViewById(R.id.rl_swipe_up_holder);
rlSwipe1 = (RelativeLayout) findViewById(R.id.rl_swipe_up_1);
rlSwipe2 = (RelativeLayout) findViewById(R.id.rl_swipe_up_2);
rlSwipe2.setVisibility(View.GONE);
rlSwipeHolder.setOnTouchListener(new OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = event.getY();
break;
case MotionEvent.ACTION_UP: {
float endY = event.getY();
if (endY < startY) {
System.out.println("Move UP");
rlSwipeHolder.setVisibility(View.VISIBLE);
rlSwipe1.setVisibility(View.VISIBLE);
rlSwipe2.setVisibility(View.VISIBLE);
} else {
rlSwipeHolder.setVisibility(View.VISIBLE);
rlSwipe1.setVisibility(View.VISIBLE);
rlSwipe2.setVisibility(View.GONE);
}
}
}
return true;
}
});
}
}
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:background="#FFFFFF"
tools:context="com.app.swipeup.SwipeUpActivity" >
<RelativeLayout
android:id="#+id/rl_swipe_up_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#0000FF"
android:padding="5dp" >
<RelativeLayout
android:id="#+id/rl_swipe_up_1"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="#585858" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/rl_swipe_up_2"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_below="#+id/rl_swipe_up_1"
android:background="#FE2E2E" >
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
Edit
Like this video i have to open the layout and close the layout (or swipe up the layout and swipe down the layout) when clicking the button
Create object of your onTouchListenr.
OnTouchListener ot = new OnTouchListener(){-------- YOUR CODE ---}
on enable button click
rlSwipeHolder.setOnTouchListener(ot);
on disable button clik
rlSwipeHolder.setOnTouchListener(null);
This is not the exact solution for this, but i'm posting here, because it may help others.
Answer
I saw lot of solutions for setOnTouchListener after setOnClickListener but i didn't get. So, i followed the animation for layout up and down as discussed in this link
and i did minute changes to the code as
Activity
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
public class SwipeUpActivity extends Activity {
RelativeLayout mRelativeLayout;
RelativeLayout mRelativeLayoutHeader;
ValueAnimator mAnimator;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe_up);
mRelativeLayout = (RelativeLayout) findViewById(R.id.expandable);
// mLinearLayout.setVisibility(View.GONE);
mRelativeLayoutHeader = (RelativeLayout) findViewById(R.id.header);
// Add onPreDrawListener
mRelativeLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
mRelativeLayout.getViewTreeObserver().removeOnPreDrawListener(this);
mRelativeLayout.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
mRelativeLayout.measure(widthSpec, heightSpec);
mAnimator = slideAnimator(0, mRelativeLayout.getMeasuredHeight());
return true;
}
});
mRelativeLayoutHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mRelativeLayout.getVisibility() == View.GONE) {
expand();
} else {
collapse();
}
}
});
}
private void expand() {
// set Visible
mRelativeLayout.setVisibility(View.VISIBLE);
mAnimator.start();
}
private void collapse() {
int finalHeight = mRelativeLayout.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
// Height=0, but it set visibility to GONE
mRelativeLayout.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// Update Height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = mRelativeLayout.getLayoutParams();
layoutParams.height = value;
mRelativeLayout.setLayoutParams(layoutParams);
}
});
return animator;
}
}
Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#FCF">
</RelativeLayout>
<RelativeLayout
android:id="#+id/expandable"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_below="#+id/header"
android:background="#FFF">
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
I have a (Sherlock)FragmentActivity with 2 tabbed fragments. The left fragment is a GridView that displays pictures of an album and the right fragment consists of a ViewPager that is used to view individual pictures. From the left fragment you can scroll through the pictures and select one. Tabbing (or swiping) over to the right fragment will show the picture and because it is a ViewPager you can swipe to the preceding or the next picture.
This works great except that the FragmentActivity wants to intercept the right swipe and move back to the left tab. I would like to prevent the FragmentActivity from intercepting the swipes when I am on the right tab. If I had to disable swiping between tabs altogether it would be satisfactory. I just want the swiping to be dedicated to the current tab and not be used to move between tabs.
The following images indicate the current behavior. The right image shows what happens when I do a swipe to the right. As you can see the left tab starts to appear. I want the swipe to instead apply to the right tab only so that I can swipe between the images without the left tab appearing.
I see solutions to control swiping within a ViewPager but have yet to find a solution to control swiping between tabbed fragments.
Here is the xml for the GridView fragment and the ViewPager fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<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="100dip"
android:gravity="center"
android:horizontalSpacing="4dip"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="4dip" />
</FrameLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>
Here a code summary of the ViewPager fragment:
public class FragmentFlash extends SherlockFragment {
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private ViewPager pager = null;
private int pagerPosition;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pagerPosition = 0;
// Gesture detection
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.flash, container, false);
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setOnTouchListener(gestureListener);
return v;
}
class MyGestureDetector extends SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 10;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 50;
#Override
public boolean onDown(MotionEvent e) {
return true;//false; make onFling work with fragments
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
else
// right to left swipe
if(distanceX > SWIPE_MIN_DISTANCE) {
if (pagerPosition < imageUrls.length-1)
pager.setCurrentItem(++pagerPosition);
// left to right swipe
} else if (distanceX < -SWIPE_MIN_DISTANCE) {
if (pagerPosition > 0)
pager.setCurrentItem(--pagerPosition);
}
return true;
} catch (Exception e) {
// nothing
}
return false;
}
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
ImagePagerAdapter(String[] images) {
this.images = images;
inflater = mContext.getLayoutInflater();
}
#Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public void finishUpdate(View container) {
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object instantiateItem(View view, int position) {
final View imageLayout = inflater.inflate(R.layout.item_pager_image, null);
final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
byte[] image = ;//get byte array from file at images[position];
if (null != image) {
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
imageView.setImageBitmap(bitmap);
}
((ViewPager) view).addView(imageLayout, 0);
return imageLayout;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public void startUpdate(View container) {
}
}
public void pagerPositionSet(int pagerPosition, String[] imageUrls) {
Log.i(Flashum.LOG_TAG, "FragmentFlash pagerPositionSet: " + pagerPosition);
if (pagerPosition >= 0)
this.pagerPosition = pagerPosition;
if (pager != null) {
pager.setAdapter(new ImagePagerAdapter(imageUrls));
pager.setCurrentItem(this.pagerPosition);
}
}
}
This is the item_pager_image.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="1dip" >
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="#string/descr_image" />
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
Ok, I finally figured this out. Laurence Dawson was on the right track but instead of applying the CustomViewPager to the fragment it needs to be applied to the FragmentActivity. You see, switching between tabs, which is managed by the activity, is also a ViewPager adaptor. Thus, xml for the activity is
<TabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<com.Flashum.CustomViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</TabHost>
And the custom ViewPager is as suggested except that that the constructor enables it to cause onInterceptTouchEvent to return false. This prevents the FragmentActivity from acting on the swipe so that it can be dedicated to the fragment!
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = **false**;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
You need to override the onInterceptTouchEvent method for your ViewPager, you can do this by extending ViewPager or visit this link for a great tutorial on adding this:
http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html