mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
adPageSelectListener.onPageChanged(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
You can create your own NonSwipableViewPager like this:
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
this(context, null);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
just override OnTouchEvent and onInterceptTouchEvent method and return false.
Related
I worked on android swipe gestures, i applied swipe gesture on Item inside recycler view and recycler view is inside fragment and then fragment is inside activity and activity has Scroll View, The problem was that parent activity was intercepting swipe gesture of item inside child recycler view, After so much hard i found solution and this code is working fine, Is there any other better solution to this problem? if yes then post it in answer otherwise vote my code so that i can use it in my app without any fear of failure. Here is my code
listingView.setOnTouchListener(new OnSwipeTouchListener(myContext)
{
public void onClick() {
ViewListing();
}
// #Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
LockableScrollView.setScrollingEnabled(true);
break;
case MotionEvent.ACTION_MOVE:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > 20)
{
LockableScrollView.setScrollingEnabled(false);
// Left to Right swipe action
if (x2 > x1)
{
hideSidePanel();
LockableScrollView.setScrollingEnabled(true);
}
else
//MH: Right to Left Swipe
{
showSidePanel();
LockableScrollView.setScrollingEnabled(true);
}
}
break;
}
return super.onTouch(v, event);
}
});
Lockable Scroll View code
public class LockableScrollView extends ScrollView {
#Override
public void setClipChildren(boolean clipChildren) {
clipChildren=false;
super.setClipChildren(clipChildren);
}
#Override
public void setFocusable(int focusable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
focusable=View.NOT_FOCUSABLE;
}
super.setFocusable(focusable);
}
// true if we can scroll (not locked)
// false if we cannot scroll (locked)
private static boolean mScrollable = true;
public LockableScrollView(Context context) {
super(context);
}
public LockableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public static void setScrollingEnabled(boolean enabled) {
mScrollable = enabled;
}
public static boolean isScrollable() {
return mScrollable;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//MH: if we can scroll pass the event to the superclass
if (mScrollable) return super.onTouchEvent(ev);
//MH: only continue to handle the touch event if scrolling enabled
return mScrollable; // mScrollable is always false at this point
default:
return super.onTouchEvent(ev);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//MH: Don't do anything with intercepted touch events if
//MH: we are not scrollable
if (!mScrollable) return false;
else return super.onInterceptTouchEvent(ev);
}
}
I have build a list of data with a recyclerview. Everything works as expected. But I want to acces some data in my adapter when I click on a cell. The click works. But I don't know how to acces my events list.
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ViewHolder> {
private final LayoutInflater layoutInflater;
private final Context context;
private ArrayList<Event> events;
public ExampleAdapter(Context context, ArrayList<Event> events) {
this.context = context;
layoutInflater = LayoutInflater.from(context);
this.events = events;
}
#Override
public ExampleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(layoutInflater.inflate(R.layout.activity_row, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
//holder.textView.setText(titles[position]);
holder.title.setText(events.get(position).getTitle());
holder.time.setText(events.get(position).getTime());
holder.places.setText(events.get(position).getPlacesLeft());
}
public void add(ArrayList<Event> events){
this.events = events;
this.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return events == null ? 0 : events.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView title;
TextView time;
TextView places;
ViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.activity_title);
time = (TextView) view.findViewById(R.id.activity_time);
places = (TextView) view.findViewById(R.id.activity_places);
//textView = (TextView) view.findViewById(R.id.text_view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("ViewHolder", "onClick--> position = " + getPosition());
}
});
}
}
}
I have declared the onclick listener in the ViewHolder class. The click listener works as expected. But I want to acces the data in my events array. The only problem is that I can't acces it.
your onclick should be inside your onBindViewHolder
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
//holder.textView.setText(titles[position]);
holder.title.setText(events.getTitle());
holder.time.setText(events.getTime());
holder.places.setText(events.getPlacesLeft());
holder.yourview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
//access from here
Toast.makeText(yourActivity.this,holder.yourview.getText().toString(), Toast.LENGTH_SHORT).show();
}
});
}
If you just want to handle the click on the item you can do like this :
In your adapter write a function to get an event at a position :
public Event getEventAtPosition(int position) {
if (events != null && events.size() > position)
return events.get(position);
else return null;
}
Then implement a RecyclerTouchListener :
public interface ClickListener{
void onClick(View view,int position);
void onLongClick(View view,int position);
}
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private ClickListener clicklistener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener){
this.clicklistener=clicklistener;
gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child=recycleView.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null){
clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child=rv.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
clicklistener.onClick(child,rv.getChildAdapterPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
Finally, you can use it this way :
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
recyclerView, new ClickListener() {
#Override
public void onClick(View view, final int position) {
Event event= ((EventListAdapter)recyclerView.getAdapter()).getEventAtPosition(position);
}
#Override
public void onLongClick(View view, int position) {
}
}));
This way, you have only 1 ClickListener for all your recycler view, this is more optimal than declaring a listener for each item.
For more informations about RecyclerView and onClick, check this topic : RecyclerView onClick
I'm working on a collab project. My goal here is to display the ViewPager item position. I have tried several possible solutions such as trying getting from the addOnPageChangeListener and displaying the position, made a function to in IntroView class to get the position but couldn't get what I wanted. Here's my code structure. Any help would be gladly appreciated. Thanks in advance.
InroActivity.java
public class IntroActivity extends DialogFacebookActivity {
private IntroView mIntroView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ChatterApplication.getApplicationComponent().inject(this);
mIntroView = new IntroView(this);
setContentView(mIntroView);
mIntroView.setAdapter(new IntroPagerAdapter(getSupportFragmentManager()));
}
Here's my IntroView.java
public class IntroView extends CoordinatorLayout {
#Bind(R.id.view_pager)
ViewPager mViewPager;
public IntroView(Context context) {
super(context);
init();
}
public IntroView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public IntroView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setAdapter(#NonNull PagerAdapter pagerAdapter) {
mViewPager.setAdapter(pagerAdapter);
}
public void goToNextPage() {
mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, true);
}
public int displayItem(){
return mViewPager.getCurrentItem();
}
private void init() {
inflate(getContext(), R.layout.view_intro, this);
ButterKnife.bind(this);
}
}
Here's my IntroFragment.java
public class IntroFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
#Inject
EventBus mEventBus;
IntroView iv;
ViewPager vp;
public IntroFragment() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
ChatterApplication.getApplicationComponent().inject(this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final int sectionNumber = getArguments().getInt(ARG_SECTION_NUMBER);
IntroPageView view;
if (sectionNumber == IntroPagerAdapter.TUTORIAL_PAGE_COUNT) {
view = new IntroPageViewLast(getContext());
} else {
view = new IntroPageView(getContext(), sectionNumber);
}
iv= new IntroView(getContext());
vp =(ViewPager) iv.findViewById(R.id.view_pager);
Toast.makeText(getContext(),"You are in: " + vp.getCurrentItem() ,Toast.LENGTH_LONG).show();
return view;
}
public static IntroFragment newInstance(int sectionNumber) {
IntroFragment fragment = new IntroFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
}
Here's my IntroPageView which is used by my fragment
public class IntroPageView extends RelativeLayout {
#Bind(R.id.intro_skip)
TextView mSkipButton;
#Bind(R.id.intro_tos_disclaimer_link)
TextView disclaimer;
#Bind(R.id.section_image)
ImageView mImageView;
private IntroPageViewListener mEventListener;
public IntroPageView(Context context, int sectionNumber) {
super(context);
init(sectionNumber);
}
public void setListener(IntroPageViewListener listener) {
this.mEventListener = listener;
}
protected void init(int sectionNumber) {
inflate(getContext(), R.layout.view_intro_fragment, this);
ButterKnife.bind(this);
mImageView.setImageResource(IntroPagerAdapter.TUTORIAL_IMAGE_IDS[sectionNumber - 1]);
}
Here's my *IntroPagerAdapter
public class IntroPagerAdapter extends FragmentPagerAdapter {
public static final int[] TUTORIAL_IMAGE_IDS = {
R.drawable.one,
R.drawable.two,
R.drawable.third,
R.drawable.four
};
public static final int TUTORIAL_PAGE_COUNT = TUTORIAL_IMAGE_IDS.length;
public IntroPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
int sectionNumber = position + 1;
return IntroFragment.newInstance(sectionNumber);
}
#Override
public int getCount() {
return TUTORIAL_PAGE_COUNT;
}
}
Turns out I forgot to use the butter ButterKnife.bind(this); while initializing my ViewPager. Hence, I was able to use addOnPageChangeListener to get the position. Here's the solution:
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Toast.makeText(getApplicationContext(), "You are in.....: " + (position + 1),Toast.LENGTH_LONG).show();
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I have an Activity that uses a ViewPager, within this ViewPager is a TouchImageView (an ImageView that detects gestures and zooms/moves accordingly).
Now I want to change some things in the UI whenever the image is clicked, but because the TouchImageView is declared in the PagerAdapter I can't reach it and if I would setup something on the side of the PagerAdapter I couldn't reach the UI components I want to change (I would also like to use the same adapter somewhere else in my app when I got this working). I've tried setting up an onClickListener on the ViewPager itself, but that doesn't trigger. Now I really don't know what to do.
Here is the adapter:
public class FullScreenImageAdapter extends PagerAdapter {
private ArrayList<MediaFile> images;
public FullScreenImageAdapter( ArrayList<MediaFile> images) {
this.images = images;
}
#Override
public int getCount() {
return images.size();
}
#Override
public View instantiateItem(ViewGroup container, int position) {
TouchImageView img = new TouchImageView(container.getContext());
Bitmap bitmap = BitmapFactory.decodeFile(images.get(position).getPath());
img.setImageBitmap(bitmap);
container.addView(img, ViewPager.LayoutParams.MATCH_PARENT, ViewPager.LayoutParams.MATCH_PARENT);
return img;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
And here is the method that interacts with it (in the ProjectOverviewActivity class):
private void viewPicture(final int position) {
View decorView = getWindow().getDecorView();
statusBarVisibility = decorView.getSystemUiVisibility();
// Hide the status bar.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
FullScreenImageAdapter imageAdapter = new FullScreenImageAdapter(mediaFiles);
final ViewPager viewPager = (ViewPager) findViewById(R.id.image_pager);
viewPager.setAdapter(imageAdapter);
viewPager.setCurrentItem(position);
View fancyBox = findViewById(R.id.fancyBox);
fancyBox.setVisibility(View.VISIBLE);
viewPager.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View btnClose = findViewById(R.id.fancyBoxBtnClose);
View btnPrev = findViewById(R.id.fancyBoxBtnPrev);
View btnNext = findViewById(R.id.fancyBoxBtnNext);
if (overlayButtonsVisible) {
btnClose.setVisibility(View.GONE);
btnPrev.setVisibility(View.GONE);
btnNext.setVisibility(View.GONE);
} else {
btnClose.setVisibility(View.VISIBLE);
if (viewPager.getCurrentItem() > 0) {
btnPrev.setVisibility(View.VISIBLE);
}
if (viewPager.getCurrentItem() < (mediaFiles.size() - 1)) {
btnNext.setVisibility(View.VISIBLE);
}
}
overlayButtonsVisible = !overlayButtonsVisible;
}
});
View fancyBoxBtnClose = findViewById(R.id.fancyBoxBtnClose);
final View fancyBoxBtnPrev = findViewById(R.id.fancyBoxBtnPrev);
final View fancyBoxBtnNext = findViewById(R.id.fancyBoxBtnNext);
fancyBoxBtnClose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View decorView = getWindow().getDecorView();
// Show the status bar.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
decorView.setSystemUiVisibility(statusBarVisibility);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, statusBarVisibility);
}
findViewById(R.id.fancyBox).setVisibility(View.GONE);
setViewAndChildrenEnabled(findViewById(R.id.layoutProjectOverview), true);
overlayButtonsVisible = false;
}
});
fancyBoxBtnPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
if (viewPager.getCurrentItem() == 0) {
fancyBoxBtnPrev.setVisibility(View.GONE);
}
}
});
fancyBoxBtnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
if (viewPager.getCurrentItem() == (mediaFiles.size() - 1)) {
fancyBoxBtnNext.setVisibility(View.GONE);
}
}
});
}
You can try this
Update:
I think you should create your custom ViewPager with GestureDetector
Example:
public class ClickableViewPager extends ViewPager {
private OnItemClickListener mOnItemClickListener;
public ClickableViewPager(Context context) {
super(context);
setup();
}
public ClickableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
private void setup() {
final GestureDetector tapGestureDetector = new GestureDetector(getContext(), new TapGestureListener());
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
tapGestureDetector.onTouchEvent(event);
return false;
}
});
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public interface OnItemClickListener {
void onItemClick(int position);
}
private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if(mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(getCurrentItem());
}
return true;
}
}
}
and then in your activity
ClickableViewPager viewPager = (ClickableViewPager) findViewById(R.id.viewPager);
viewPager.setOnItemClickListener(new ClickableViewPager.OnItemClickListener() {
#Override
public void onItemClick(int position) {
// HADNLE YOUR CLICKS
}
});
SOURCE
In an attempt to write a bit less code every time I wanted a SeekBar and a corresponding TextView showing it's numerical value, I wrote the following abstract class:
abstract public class SeekBarWrapper {
SeekBar bar;
TextView valueText;
int value = 0;
int minValue;
int divisor;
public SeekBarWrapper(SeekBar sb, TextView tv, int value, int minValue,
int divisor){
this.bar = sb;
this.valueText = tv;
this.value = value;
this.minValue = minValue;
this.divisor = divisor;
setListener();
}
private void setListener(){
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) { }
#Override
public void onStartTrackingTouch(SeekBar seekBar) { }
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(!fromUser) return;
value = progress + minValue;
valueText.setText(Integer.toString(value/divisor));
sendValue();
}
});
}
abstract protected void sendValue();
public void updateValue(int newValue){
if(newValue == value) return;
value = newValue;
valueText.setText(Integer.toString(value));
bar.setProgress(value*divisor-minValue);
}
}
For each concrete SeekBar I'll write a nested class, for example:
class VolumeBarWrapper extends SeekBarWrapper{
public VolumeBarWrapper(SeekBar s, TextView t, int v, int min, int div){
super(s, t, v, min, div);
}
public void sendValue(){
someCallback.volume(this.value);
}
}
And instantiate like so:
VolumeBarWrapper volume;
// later:
volume = new VolumeBarWrapper((SeekBar) view.findViewById(R.id.volume_bar),
(TextView) view.findViewById(R.id.volume_value), 300, 0, 70);
It's functional, and seemingly an improvement. What I would like to know:
Is there is some way to make this an anonymous inner class, or another method to further condense the per-instance code?
And less pressingly:
Am I abusing the "wrapper" label, doesn't it have some specialized meaning in pattern-speak?
Is this design "bad" from an OOP perspective (I'm still trying to school myself in this regard)?
You can always make a better SeekBar , and use it everywhere:
public class VersatileSeekBar extends SeekBar implements SeekBar.OnSeekBarChangeListener {
private TextView mTextView;
private ChangeHandler mChangeHandler;
public void bindDisplayToChange(TextView textView,ChangeHandler handler) {
mTextView = textView;
mChangeHandler = handler;
}
public VersatileSeekBar(Context context) {
super(context);
init();
}
public VersatileSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public VersatileSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if(mChangeHandler != null && mTextView != null){
mChangeHandler.onChange(i,mTextView);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
private void init(){
this.setOnSeekBarChangeListener(this);
}
public static abstract class ChangeHandler{
public abstract void onChange(int value,TextView textView);
}
}
Code to call :
myVersatileSeekBar.bindDisplayToChange(myTextView, new VersatileSeekBar.ChangeHandler() {
#Override
public void onChange(int value, TextView textView) {
textView.setText("level :" + value * 100);
}
});