I disable swipe the ViewPager with TabLayout as below:
public class NonScrollableViewPager extends ViewPager {
public NonScrollableViewPager(Context context) {
super(context);
init(context, null);
}
public NonScrollableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
#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;
}
}
How to prevent other tabs clickable when select one of tabs, then computation complected then enable the clickable. ViewPager.setClickable(false) and setEnabled() don't work
disable clickable
// do something
enable clickable
How to do that?
I am assuming that you are using TabLayout along with ViewPager. So, you need to implement as follows
LinearLayout tabStrip = ((LinearLayout) your_tab_layout.getChildAt(0));
for(int i = 0; i < tabStrip.getChildCount(); i++) {
tabStrip.getChildAt(i).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
}
For API 24 and above
your_tab_layout.clearOnTabSelectedListeners();
Hope this helps
Related
I am trying to make the linechart from mpandroidchart ignore the fragmentviewpager and only move the linechart and not the viewpager when touching the view. My question is how can I archive this?
I found this solution but dont know how to implement it Maybee you guys can help me understand how to implement it?
https://github.com/PhilJay/MPAndroidChart/issues/1885#issuecomment-267568663
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumberOfTabs;
public PagerAdapter(FragmentManager fm, int NumberOfTabs) {
super(fm);
this.mNumberOfTabs = NumberOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
IncomeOutcomeOverviewFragment incomeOutcomeOverviewFragment = new IncomeOutcomeOverviewFragment();
return incomeOutcomeOverviewFragment;
case 1:
IncomeFragment incomeFragment = new IncomeFragment();
return incomeFragment;
case 2:
OutcomeFragment outcomeFragment = new OutcomeFragment();
return outcomeFragment;
default:
return null;
}
}
#Override
public int getCount() {
return mNumberOfTabs;
}
}
I think what you want is nor swipeable view pager for that you have to create custom view pager like this
UPDATE changes suggested by #anomynous
public class NonSwipeableViewPager extends ViewPager {
boolean enabled = false;
public NonSwipeableViewPager(Context context) {
super(context);
setMyScroller();
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setMyScroller();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return false;
}
return super.onInterceptTouchEvent(event);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return false;
}
return super.onTouchEvent(event);
}
//down one is added for smooth scrolling
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
#Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
}
}
public void setPagingDisabled(boolean enabled) {
this.enabled = enabled;
}
}
Then on my linechart I used onChartGestureStart and onChartGestureEnd to enable or disable the pageview:
#Override
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
nonSwipeableViewPager.setPagingDisabled(true);
}
#Override
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
nonSwipeableViewPager.setPagingDisabled(false);
}
replace default viewpager with custom one in xml
You need you to disable touch for your chart, you can use this code,
chart.setTouchEnabled(true);
I have a Tabbed Activity: a user can swipe to the right or to the left to change the screens. At some point I want to record an audio and while it is being recorder the user is not supposed to change the screens.
Question: How to restrict a user from changing screens (swiping) in ViewPager?
I tried to figure out how to do that using ViewPager API but I didn't manage to find a proper way (there are hundreds or may be even thousand methods in ViewPager none of which is likely to do what I want).
You can extend the ViewPager class and use this code.
public class LockableViewPager extends ViewPager {
private boolean swipeable;
public LockableViewPager(Context context) {
super(context);
}
public LockableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.swipeable = true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return this.swipeable && super.onInterceptTouchEvent(event);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return this.swipeable && super.onTouchEvent(event);
}
public void setSwipeable(boolean swipeable) {
this.swipeable = swipeable;
}
}
Then in your Fragment or Activity you can just call mViewPager.setSwipeable(false); to make it unswipeable.
Create a custom viewPager like below
public class CustomViewPager extends ViewPager {
private boolean enabled = true;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
enabled = true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
if (enabled) {
return super.onInterceptTouchEvent(arg0);
} else {
return false;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Then simply call viewPager.setPagingEnabled(false);
I want to fire a event when the same item is selected in spinner. Method
#Override
public void onItemSelected(AdapterView<?> parent, View arg1, int position,
long arg3) {
}
is called only when we different selection is made. My Purpose is to display a toast when any item is selected either the same item is reselected or different selection is made.
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
above method does not solve my problem.
i have found that old selection is kept at variable called mOldSelectedPosition in the hierarcy of the spinner. Spinner is using this value to check if the same item selected or not , and if it is the same , it ignores. If we dont wanna ignore this What i did is some dirty code using reflection.
package com.aradiom.amc.nativecomponents;
import java.lang.reflect.Field;
import android.content.Context;
import android.util.Log;
import android.widget.Spinner;
public class SpinnerTrigger extends Spinner {
public SpinnerTrigger(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
public void setSelection(int position, boolean animate) {
ignoreOldSelectionByReflection();
super.setSelection(position, animate);
}
private void ignoreOldSelectionByReflection() {
try {
Class<?> c = this.getClass().getSuperclass().getSuperclass().getSuperclass();
Field reqField = c.getDeclaredField("mOldSelectedPosition");
reqField.setAccessible(true);
reqField.setInt(this, -1);
} catch (Exception e) {
Log.d("Exception Private", "ex", e);
// TODO: handle exception
}
}
#Override
public void setSelection(int position) {
ignoreOldSelectionByReflection();
super.setSelection(position);
}
}
This class will always invalidate the oldselection value , so that every time on click event gets triggered.
It may not be perfect solution. Use with caution. :)
Hopefully this help. I tried and it works
/** Spinner extension that calls onItemSelected even when the selection is the same as its previous value */
public class NDSpinner extends Spinner {
public NDSpinner(Context context)
{ super(context); }
public NDSpinner(Context context, AttributeSet attrs)
{ super(context, attrs); }
public NDSpinner(Context context, AttributeSet attrs, int defStyle)
{ super(context, attrs, defStyle); }
#Override public void
setSelection(int position, boolean animate)
{
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position, animate);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
#Override public void
setSelection(int position)
{
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
}
Since my reputation is not high enough to comment directly on #Suat 's answer, I tried that method, it works like charm, but I'm not clear what the side effects could be.
Something I want to add is, additional constructors should be added to avoid errors.
public SpinnerTrigger(Context context, AttributeSet attrs, int defStyle)
{ super(context, attrs, defStyle); }
public SpinnerTrigger(Context context, AttributeSet attrs){
super(context,attrs);
}
You can add a method name on your item selected METHOD
Spinner `Spinner1`=(Spinner)findViewById(R.id.`declareid`)
oBject has been declared for spinner
#Override
public void onItemSelected(AdapterView<?> parent, View arg1, int position,
long arg3)
{
ItemOnChange();
}
private void ItemOnChange() {
if(Spinner1.getSelectedItemPosition()>0){
pd=ProgressDialog.show(this,"","Loading, Please wait .. ",true);
final int spinner=Spinner1.getSelectedItemPosition();
final Handler ThreadCallback=new Handler();
final Runnable runInCityThread=new Runnable(){
public void run(){
fnBindspimmer2();
pd.dismiss();
}
};
new Thread(){
#Override public void run(){
Spinner2values();
ThreadCallback.post(runInCityThread);
}
}.start();
}
}
use click listener to fulfill your requirement. as direct click listener on spinner doesn't supported so make a class extend spinner and over ride on click method and in this method do what you want to do.
I have a problem. I have my own scrollview, but it doesn't work. The scrollbar appears, but when I try to use it doesn't work. I have tried a lot of things, but none work. The code is:
#SuppressLint("ClickableViewAccessibility") public class myScrollView extends ScrollView {
private boolean enableScrolling = true;
public boolean isEnableScrolling() {
return enableScrolling;
}
public void setEnableScrolling(boolean enableScrolling) {
this.enableScrolling = enableScrolling;
}
public myScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public myScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public myScrollView(Context context) {
super(context);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isEnableScrolling()) {
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (isEnableScrolling()) {
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
}
}
Inside of this scroll, I have a relativeLayout and inside of this a View. In the View I draw some bitmaps. They number more than it can display the screen.
The XML is:
<com.edjume.myScrollView
android:id="#+id/scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/table">
<RelativeLayout
android:id="#+id/table"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
</RelativeLayout>
</com.edjume.myScrollView>
And in the activity I use:
RelativeLayout ll = (RelativeLayout) findViewById(R.id.table);
ll.addView(new Table(this));
And finally, in my View (Table) has a OnDraw() and a onTouchEvent(). In the onTouchEvent I use the options ACTION_DOWN, ACTION_MOVE and ACTION_UP.
I believe
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (isEnableScrolling()) {
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
should be:
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (isEnableScrolling()) {
return super.onTouchEvent(ev);
} else {
return false;
}
}
I am using webview in android to play a video. The problem is that video is playing once. I have seen some answers about how to fix it, but still not working. Here's my code:
public class MyChromeClient extends WebChromeClient implements
OnCompletionListener, OnErrorListener {
private Activity _activity;
private VideoView mCustomVideoView;
private LinearLayout mContentView;
private FrameLayout mCustomViewContainer;
private WebChromeClient.CustomViewCallback mCustomViewCallback;
static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT, Gravity.CENTER);
public MyChromeClient(Activity context) {
super();
_activity = context;
}
#Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
FrameLayout frame = (FrameLayout) view;
if (frame.getFocusedChild() instanceof VideoView) {
mCustomVideoView = (VideoView) frame.getFocusedChild();
frame.removeView(mCustomVideoView);
_activity.setContentView(mCustomVideoView);
mCustomVideoView.setOnCompletionListener(this);
mCustomVideoView.setOnErrorListener(this);
mCustomVideoView.start();
}
}
}
public void onHideCustomView() {
if (mCustomVideoView == null)
return;
// Hide the custom view.
mCustomVideoView.setVisibility(View.GONE);
// Remove the custom view from its container.
mCustomViewContainer.removeView(mCustomVideoView);
mCustomVideoView = null;
mCustomViewContainer.setVisibility(View.GONE);
mCustomVideoView.stopPlayback();
mCustomViewCallback.onCustomViewHidden();
// Show the content view.
mContentView.setVisibility(View.VISIBLE);
}
public void onCompletion(MediaPlayer mp) {
//Intent intent = new Intent(_activity, _activity.getClass());
//intent.setClass(_activity, _activity.getClass());
//_activity.startActivity(intent);
//_activity.finish();
}
public boolean onError(MediaPlayer mp, int what, int extra) {
return true;
}
}
try this
add this in show method
WebChromeClient.CustomViewCallback CustomViewCallback; mCustomViewCallback = callback;
then in hide method...
mCustomViewCallback.onCustomViewHidden(); mCustomViewCallback = null; HTML5WebView.this.goBack();
EDIT :-
public class HTML5WebView extends WebView {
static final String LOGTAG = "HTML5WebView";
private void init(Context context) {
mContext = context;
Activity a = (Activity) mContext;
mLayout = new FrameLayout(context);
mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(a).inflate(R.layout.custom_screen, null);
mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.main_content);
mCustomViewContainer = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.fullscreen_custom_content);
mLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
// Configure the webview
WebSettings s = getSettings();
s.setBuiltInZoomControls(true);
s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
s.setUseWideViewPort(true);
s.setLoadWithOverviewMode(true);
s.setSaveFormData(true);
s.setJavaScriptEnabled(true);
mWebChromeClient = new MyWebChromeClient();
setWebChromeClient(mWebChromeClient);
setWebViewClient(new WebViewClient());
setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
s.setDomStorageEnabled(true);
mContentView.addView(this);
}
public HTML5WebView(Context context) {
super(context);
init(context);
}
public HTML5WebView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public HTML5WebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public FrameLayout getLayout() {
return mLayout;
}
public boolean inCustomView() {
return (mCustomView != null);
}
public void hideCustomView() {
mWebChromeClient.onHideCustomView();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if ((mCustomView == null) && canGoBack()){
goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
private class MyWebChromeClient extends WebChromeClient {
private Bitmap mDefaultVideoPoster;
private View mVideoProgressView;
FrameLayout frame;
#Override
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
{
HTML5WebView.this.setVisibility(View.GONE);
isVideoPlaying = true;
// if a view already exists then immediately terminate the new one
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomViewContainer.addView(view);
mCustomView = view;
frame = (FrameLayout) mCustomView;
mCustomViewCallback = callback;
VideoView mVideoView;
if(frame.getFocusedChild() instanceof VideoView){
mVideoView = (VideoView) frame.getFocusedChild();
}
mCustomViewContainer.setVisibility(View.VISIBLE);
}
#Override
public void onHideCustomView() {
if (mCustomView == null)
return;
// Hide the custom view.
mCustomView.setVisibility(View.GONE);
// Remove the custom view from its container.
mCustomViewContainer.removeView(mCustomView);
mCustomView = null;
mCustomViewContainer.setVisibility(View.GONE);
mCustomViewCallback.onCustomViewHidden();
mCustomViewCallback = null;
HTML5WebView.this.setVisibility(View.VISIBLE);
HTML5WebView.this.goBack();
}
}
}
I would like to offer an alternative, it may not be perfect, but from a web programming point of view, after beating my head against this for some time, the trick was to covert the video to base64 and the feed it to the source tag (jquery in my case). If it isn't in the assets folder it can't get confuse!