I want to make horizontally infinite viewpager, which scroll continue both side left and right.
Anyone have idea then please let me know.
I have implement these all classes below please check it and let me know if any one have any new idea.
1. Make **HorizontalInfiniteCycleViewPager** class.
package com.test.HorizontalInfiniteCycleViewPager;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
/**
* Created by GIGAMOLE on 7/27/16.
*/
public class HorizontalInfiniteCycleViewPager extends ViewPager implements ViewPageable {
private InfiniteCycleManager mInfiniteCycleManager;
public HorizontalInfiniteCycleViewPager(final Context context) {
super(context);
init(context, null);
}
public HorizontalInfiniteCycleViewPager(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(final Context context, final AttributeSet attributeSet) {
mInfiniteCycleManager = new InfiniteCycleManager(context, this, attributeSet);
}
public float getMinPageScaleOffset() {
return mInfiniteCycleManager == null ? 0.0F : mInfiniteCycleManager.getMinPageScaleOffset();
}
public void setMinPageScaleOffset(final float minPageScaleOffset) {
if (mInfiniteCycleManager != null)
mInfiniteCycleManager.setMinPageScaleOffset(minPageScaleOffset);
}
public float getCenterPageScaleOffset() {
return mInfiniteCycleManager == null ? 0.0F : mInfiniteCycleManager.getCenterPageScaleOffset();
}
public void setCenterPageScaleOffset(final float centerPageScaleOffset) {
if (mInfiniteCycleManager != null)
mInfiniteCycleManager.setCenterPageScaleOffset(centerPageScaleOffset);
}
public float getMinPageScale() {
return mInfiniteCycleManager == null ? 0.0F : mInfiniteCycleManager.getMinPageScale();
}
public void setMinPageScale(final float minPageScale) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.setMinPageScale(minPageScale);
}
public float getMaxPageScale() {
return mInfiniteCycleManager == null ? 0.0F : mInfiniteCycleManager.getMaxPageScale();
}
public void setMaxPageScale(final float maxPageScale) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.setMaxPageScale(maxPageScale);
}
public boolean isMediumScaled() {
return mInfiniteCycleManager != null && mInfiniteCycleManager.isMediumScaled();
}
public void setMediumScaled(final boolean mediumScaled) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.setMediumScaled(mediumScaled);
}
public int getScrollDuration() {
return mInfiniteCycleManager == null ? 0 : mInfiniteCycleManager.getScrollDuration();
}
public void setScrollDuration(final int scrollDuration) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.setScrollDuration(scrollDuration);
}
public Interpolator getInterpolator() {
return mInfiniteCycleManager == null ? null : mInfiniteCycleManager.getInterpolator();
}
public void setInterpolator(final Interpolator interpolator) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.setInterpolator(interpolator);
}
public boolean isVertical() {
return mInfiniteCycleManager != null && mInfiniteCycleManager.isVertical();
}
public OnInfiniteCyclePageTransformListener getOnInfiniteCyclePageTransformListener() {
return mInfiniteCycleManager == null ?
null : mInfiniteCycleManager.getOnInfiniteCyclePageTransformListener();
}
public void setOnInfiniteCyclePageTransformListener(
final OnInfiniteCyclePageTransformListener onInfiniteCyclePageTransformListener
) {
if (mInfiniteCycleManager != null)
mInfiniteCycleManager.setOnInfiniteCyclePageTransformListener(onInfiniteCyclePageTransformListener);
}
#Override
public void setPageTransformer(final boolean reverseDrawingOrder, final PageTransformer transformer) {
super.setPageTransformer(
false, mInfiniteCycleManager == null ?
transformer : mInfiniteCycleManager.getInfinityCyclePageTransformer()
);
}
#Override
protected void setChildrenDrawingOrderEnabled(final boolean enabled) {
super.setChildrenDrawingOrderEnabled(InfiniteCycleManager.DEFAULT_DISABLE_FLAG);
}
#Override
public void setClipChildren(final boolean clipChildren) {
super.setClipChildren(InfiniteCycleManager.DEFAULT_DISABLE_FLAG);
}
#Override
public void setDrawingCacheEnabled(final boolean enabled) {
super.setDrawingCacheEnabled(InfiniteCycleManager.DEFAULT_DISABLE_FLAG);
}
#Override
protected void setChildrenDrawingCacheEnabled(final boolean enabled) {
super.setChildrenDrawingCacheEnabled(InfiniteCycleManager.DEFAULT_DISABLE_FLAG);
}
#Override
public void setWillNotCacheDrawing(final boolean willNotCacheDrawing) {
super.setWillNotCacheDrawing(InfiniteCycleManager.DEFAULT_ENABLE_FLAG);
}
#Override
public void setPageMargin(final int marginPixels) {
super.setPageMargin(InfiniteCycleManager.DEFAULT_PAGE_MARGIN);
}
#Override
public void setOffscreenPageLimit(final int limit) {
super.setOffscreenPageLimit(InfiniteCycleManager.DEFAULT_OFFSCREEN_PAGE_LIMIT);
}
#Override
public void setOverScrollMode(final int overScrollMode) {
super.setOverScrollMode(OVER_SCROLL_NEVER);
}
#Override
protected boolean addViewInLayout(final View child, final int index, final ViewGroup.LayoutParams params) {
return super.addViewInLayout(child, 0, params);
}
#Override
public void addView(final View child, final int index, final ViewGroup.LayoutParams params) {
super.addView(child, 0, params);
}
#Override
public void setAdapter(final PagerAdapter adapter) {
if (mInfiniteCycleManager == null) super.setAdapter(adapter);
else {
super.setAdapter(mInfiniteCycleManager.setAdapter(adapter));
mInfiniteCycleManager.resetPager();
}
}
#Override
public PagerAdapter getAdapter() {
if (mInfiniteCycleManager == null) return super.getAdapter();
return mInfiniteCycleManager.getInfiniteCyclePagerAdapter() == null ? super.getAdapter() :
mInfiniteCycleManager.getInfiniteCyclePagerAdapter().getPagerAdapter();
}
#Override
public boolean onTouchEvent(final MotionEvent ev) {
try {
return mInfiniteCycleManager == null ? super.onTouchEvent(ev) :
mInfiniteCycleManager.onTouchEvent(ev) && super.onTouchEvent(ev);
} catch (IllegalArgumentException e) {
return true;
}
}
#Override
public boolean onInterceptTouchEvent(final MotionEvent ev) {
try {
return mInfiniteCycleManager == null ? super.onInterceptTouchEvent(ev) :
mInfiniteCycleManager.onInterceptTouchEvent(ev) && super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
return true;
}
}
#Override
public void onWindowFocusChanged(final boolean hasWindowFocus) {
if (mInfiniteCycleManager != null)
mInfiniteCycleManager.onWindowFocusChanged(hasWindowFocus);
super.onWindowFocusChanged(hasWindowFocus);
}
#Override
protected void onDetachedFromWindow() {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.stopAutoScroll();
super.onDetachedFromWindow();
}
#Override
public void setCurrentItem(final int item) {
setCurrentItem(item, true);
}
#Override
public void setCurrentItem(final int item, final boolean smoothScroll) {
if (mInfiniteCycleManager != null)
super.setCurrentItem(mInfiniteCycleManager.setCurrentItem(item), true);
}
public int getRealItem() {
return mInfiniteCycleManager == null ?
getCurrentItem() : mInfiniteCycleManager.getRealItem();
}
public int getState() {
return mInfiniteCycleManager == null ?
ViewPager.SCROLL_STATE_IDLE : mInfiniteCycleManager.getState();
}
public void notifyDataSetChanged() {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.notifyDataSetChanged();
}
public void invalidateTransformer() {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.invalidateTransformer();
}
public void postInvalidateTransformer() {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.postInvalidateTransformer();
}
public void startAutoScroll(final boolean isAutoScrollPositive) {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.startAutoScroll(isAutoScrollPositive);
}
public void stopAutoScroll() {
if (mInfiniteCycleManager != null) mInfiniteCycleManager.stopAutoScroll();
}
}
Related
I am getting null pointer on back press of activity where I have used the custom view. Where am I doing wrong?? Below is my custom view class:
public class PuzzleBoardView extends View implements ViewTreeObserver.OnGlobalLayoutListener {
public static final int NUM_SHUFFLE_STEPS = 40;
Comparator<PuzzleBoard> comparator = new PuzzleBoardComparator();
PriorityQueue<PuzzleBoard> queue = new PriorityQueue<>(9999, comparator);
private PuzzleActivity activity;
private PuzzleBoard puzzleBoard;
private ArrayList<PuzzleBoard> animation;
private Random random = new Random();
private Bitmap imgBitmap;
public PuzzleBoardView(Context context) {
super(context);
setMinimumWidth(50);
activity = (PuzzleActivity) context;
animation = null;
}
public void initialize(final Bitmap imageBitmap, Activity parent) {
final int width = getWidth();
imgBitmap = imageBitmap;
Log.d("PuzzleBoardView", "initialize: width=== " + width);
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View v) {
Log.d("PuzzleBoardView", "onViewAttachedToWindow=== " + width);
puzzleBoard = new PuzzleBoard(imgBitmap, getWidth());
shuffle();
}
#Override
public void onViewDetachedFromWindow(View v) {
Log.d("PuzzleBoardView", "onViewDetachedFromWindow=== ");
onDetachedFromWindow();
}
});
}
public void clearView() {
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("TAG", "onDraw: =====");
if (puzzleBoard != null) {
Log.d("TAG", "onDraw:111 =====");
if (animation != null && animation.size() > 0) {
puzzleBoard = animation.remove(0);
puzzleBoard.draw(canvas);
if (animation.size() == 0) {
animation = null;
puzzleBoard.reset();
Toast toast = Toast.makeText(activity, "Solved! ", Toast.LENGTH_LONG);
toast.show();
} else {
this.postInvalidateDelayed(500);
}
} else {
puzzleBoard.draw(canvas);
}
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.d("PuzzleBoardView", "onDetachedFromWindow=== ");
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
public void shuffle() {
if (animation == null && puzzleBoard != null) {
// Do something. Then:
ArrayList<PuzzleBoard> boards;
for (int i = 0; i <= NUM_SHUFFLE_STEPS; i++) {
boards = puzzleBoard.neighbours();
puzzleBoard = boards.get(random.nextInt(boards.size()));
}
puzzleBoard.reset();
invalidate();
queue.clear();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (animation == null && puzzleBoard != null) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (puzzleBoard.click(event.getX(), event.getY())) {
invalidate();
if (puzzleBoard.resolved()) {
/*Toast toast = Toast.makeText(activity, "Congratulations!", Toast.LENGTH_LONG);
toast.show();*/
activity.puzzleSolved();
}
return true;
}
}
}
return super.onTouchEvent(event);
}
public void solve() {
puzzleBoard.steps = 0;
puzzleBoard.previousBoard = null;
queue.add(puzzleBoard);
PuzzleBoard prev = null;
ArrayList<PuzzleBoard> solution = new ArrayList<>();
while (!queue.isEmpty()) {
PuzzleBoard lowest = queue.poll();
if (lowest.priority() - lowest.steps != 0) {
for (PuzzleBoard toAdd : lowest.neighbours()) {
if (!toAdd.equals(prev)) {
queue.add(toAdd);
}
}
prev = lowest;
} else {
solution.add(lowest);
while (lowest != null) {
if (lowest.getPreviousBoard() == null) {
break;
}
solution.add(lowest.getPreviousBoard());
lowest = lowest.getPreviousBoard();
}
Collections.reverse(solution);
animation = solution;
invalidate();
break;
}
}
}
public PuzzleBoard getPuzzleBoard() {
return puzzleBoard;
}
public void setPuzzleBoard(PuzzleBoard puzzleBoard) {
this.puzzleBoard = puzzleBoard;
}
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Log.d("PuzzleBoardView", "onAttachedToWindow: width=== " + getWidth());
puzzleBoard = new PuzzleBoard(imgBitmap, getWidth());
shuffle();
}
}
class PuzzleBoardComparator implements Comparator<PuzzleBoard> {
#Override
public int compare(PuzzleBoard first, PuzzleBoard second) {
if (first.priority() == second.priority()) {
return 0;
} else if (first.priority() < second.priority()) {
return -1;
} else {
return 1;
}
}
}
Here is my Exception
java.lang.NullPointerException: Attempt to invoke interface method 'void android.view.View$OnAttachStateChangeListener.onViewDetachedFromWindow(android.view.View)' on a null object reference
Change your code like below.
public PuzzleBoardView(Context context) {
super(context);
setMinimumWidth(50);
activity = (PuzzleActivity) context;
animation = null;
if(activity!=null)
initialize();
}
and remove initialize method from onCreate()
I've developed a custom component in which i've implemented onClick, onLongClick and onTouchListener. Everything is working fine except that onLongClick and onClick are called twice even i make action only once. What's wrong please guide towards solution. It takes a noticeable time in calling method again i.e. ~1 sec.
Following is the code:
CustomWidget:
#BindingMethods({
#BindingMethod(type = RecordingButton.class, attribute = "progress", method = "setProgress"),
})
public class RecordingButton extends RelativeLayout {
boolean isLongPressed;
boolean isPressed;
private Context mContext;
private int progressBackground, progressColor, progressBarWidth;
private int maxProgress, progress;
private LayoutRecordingBtnBinding itemViewBinding;
private OnRecordingButtonListener listener;
private ValueAnimator progressAnimator;
private View.OnTouchListener viewTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View pView, MotionEvent pEvent) {
pView.onTouchEvent(pEvent);
// We're only interested in when the button is released.
switch (pEvent.getAction()) {
case MotionEvent.ACTION_UP:
isPressed = false;
// We're only interested in anything if our speak button is currently pressed.
if (isLongPressed) {
AppLogger.d("usm_recording_button_2", "onTouch ACTION_UP is called to release longPress");
isLongPressed = false;
// Do something when the button is released.\
if (listener != null)
listener.onStopRecording();
} else {
setTintColor(R.color.fayvo_color);
}
break;
case MotionEvent.ACTION_DOWN:
isPressed = true;
setTintColor(R.color.trans_fayvo_color);
break;
}
return false;
}
};
public RecordingButton(Context context) {
super(context);
initializeView(context, null, 0);
}
public RecordingButton(Context context, AttributeSet attrs) {
super(context, attrs);
initializeView(context, attrs, 0);
}
public RecordingButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initializeView(context, attrs, defStyleAttr);
}
private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
mContext = context;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RecordingButton, defStyleAttr, 0);
try {
maxProgress = array.getInteger(R.styleable.RecordingButton_android_max, 30);
progress = array.getInteger(R.styleable.RecordingButton_android_progress, 0);
progressBarWidth = array.getDimensionPixelSize(R.styleable.RecordingButton_progressWidth, -1);
progressColor = array.getColor(R.styleable.RecordingButton_progressColor, Integer.MAX_VALUE);
progressBackground = array.getColor(R.styleable.RecordingButton_progressBackgroundColor, Integer.MAX_VALUE);
} finally {
array.recycle();
}
itemViewBinding = LayoutRecordingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);
setListeners();
}
private void setListeners() {
this.setOnClickListener(view -> {
// check if recording is not running on long press already
// if (progressAnimator != null && progressAnimator.isRunning())
// return;
// AppLogger.d("usm_loading_btn_1", "onClick is called");
if (listener != null) {
AppLogger.d("usm_recording_button_0", "onClick is called");
listener.onClick();
}
});
/*itemViewBinding.ivCameraBtn*/
this.setOnLongClickListener(pView -> {
AppLogger.d("usm_recording_button_1.0", "onLongClick detected: already isLongPressed= " + isLongPressed + " ,isPressed= " + isPressed);
if (isLongPressed /*|| !isPressed*/) // method is calling twice , need to do action only once
return true;
setTintColor(R.color.trans_fayvo_color);
// Do something when your hold starts here.
isLongPressed = true;
AppLogger.d("usm_recording_button_1.1", "onLongClick is called");
animateInnerIcon(true);
if (listener != null)
listener.onLongClick();
return true;
});
this.setOnTouchListener(viewTouchListener);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
setValues();
}
private void setValues() {
try {
setProgress(progress);
setMaxProgress(maxProgress);
setProgressColor(progressColor);
setProgressBackgroundColor(progressBackground);
setProgressBarWidth(progressBarWidth);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setProgress(int progress) {
itemViewBinding.circularProgressBar.setProgress(progress);
}
public void setMaxProgress(int maxProgress) {
itemViewBinding.circularProgressBar.setProgressMax(maxProgress);
}
public void setProgressBarWidth(int strokeWidth) {
if (strokeWidth > -1)
itemViewBinding.circularProgressBar.setProgressBarWidth(strokeWidth);
}
public void setProgressColor(int color) {
this.progressColor = color;
if (progressColor != Integer.MAX_VALUE) {
itemViewBinding.circularProgressBar.setColor(progressColor);
}
}
public void setProgressBackgroundColor(int color) {
this.progressBackground = color;
if (progressBackground != Integer.MAX_VALUE) {
itemViewBinding.circularProgressBar.setBackgroundColor(progressBackground);
}
}
public void setTintColor(int tintColor) {
// itemViewBinding.ivCameraBtn.setForegroundTintList(new ColorStateList()[]);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
itemViewBinding.ivCameraBtn.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(mContext, tintColor)));
}
}
public void animateInnerIcon(boolean expand) {
float from = expand ? 0f : 1f;
float to = expand ? 1f : 0f;
Animator scaleXAnimator = ObjectAnimator.ofFloat(itemViewBinding.ivInnerIcon, "scaleX", from, to);
Animator scaleYAnimator = ObjectAnimator.ofFloat(itemViewBinding.ivInnerIcon, "scaleY", from, to);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.setDuration(expand ? 600 : 300);
animatorSet.start();
}
public void animateProgress() {
progressAnimator = ValueAnimator.ofFloat(0, maxProgress);
progressAnimator.addUpdateListener(animation -> {
try {
Float val = (Float) animation.getAnimatedValue();
itemViewBinding.circularProgressBar.setProgress(val);
} catch (Exception e) {
e.printStackTrace();
}
});
progressAnimator.setDuration(maxProgress * 1000);
progressAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
isLongPressed = false; // no action required on ActionUp of onTouch
if (listener != null)
listener.onStopRecording();
// reset();
}
});
progressAnimator.setInterpolator(new LinearInterpolator());
progressAnimator.start();
}
public void reset() {
AppLogger.d("usm_recording_button_2", "reset recording button");
if (progressAnimator != null)
progressAnimator.cancel();
itemViewBinding.circularProgressBar.setProgress(0);
/*itemViewBinding.ivInnerIcon.setScaleX(0f);
itemViewBinding.ivInnerIcon.setScaleY(0f);*/
if (itemViewBinding.ivInnerIcon.getScaleX() > 0)
animateInnerIcon(false);
}
public void setOnActionListener(OnRecordingButtonListener listener) {
this.listener = listener;
}
public interface OnRecordingButtonListener {
void onClick();
void onLongClick();
void onStopRecording();
}
}
I want to achieve Single RadioGroup like below image for blood group selection.
How can this be done?
I created my own RadioGridLayout which include RadioGroup code and extends GridLayout.
You can copy this code. For me working well.
After you can use this layout in your xml and customize like grid layout.
For R.styleable.RadioGridLayout_checked I used code like this:
<resources>
<declare-styleable name="RadioGridLayout">
<attr name="checked" format="integer" />
</declare-styleable>
</resources>
public class RadioGridLayout extends GridLayout {
private int mCheckedId = -1;
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener;
private void setCheckedId(#IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
AutofillManager afm = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm = getContext().getSystemService(AutofillManager.class);
}
if (afm != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm.notifyValueChanged(this);
}
}
}
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
public interface OnCheckedChangeListener {
void onCheckedChanged(RadioGridLayout group, #IdRes int checkedId);
}
private int mInitialCheckedId = View.NO_ID;
public RadioGridLayout(Context context) {
super(context);
setOrientation(VERTICAL);
init();
}
public RadioGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
}
TypedArray attributes = context.obtainStyledAttributes(
attrs,
R.styleable.RadioGridLayout,
R.attr.radioButtonStyle, 0);
int value = attributes.getResourceId(R.styleable.RadioGridLayout_checked, View.NO_ID);
if (value != View.NO_ID) {
mCheckedId = value;
mInitialCheckedId = value;
}
attributes.recycle();
init();
}
private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
}
#Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
mPassThroughListener.mOnHierarchyChangeListener = listener;
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mCheckedId != -1) {
mProtectFromCheckedChange = true;
setCheckedStateForView(mCheckedId, true);
mProtectFromCheckedChange = false;
setCheckedId(mCheckedId);
}
}
#Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof RadioButton) {
final RadioButton button = (RadioButton) child;
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
}
super.addView(child, index, params);
}
public void check(#IdRes int id) {
if (id != -1 && (id == mCheckedId)) {
return;
}
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
if (id != -1) {
setCheckedStateForView(id, true);
}
setCheckedId(id);
}
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (checkedView != null && checkedView instanceof RadioButton) {
((RadioButton) checkedView).setChecked(checked);
}
}
#IdRes
public int getCheckedRadioButtonId() {
return mCheckedId;
}
public void clearCheck() {
check(-1);
}
#Override
public GridLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new GridLayout.LayoutParams(getContext(), attrs);
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof RadioGroup.LayoutParams;
}
#Override
protected GridLayout.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams();
}
#Override
public CharSequence getAccessibilityClassName() {
return RadioGroup.class.getName();
}
public static class LayoutParams extends GridLayout.LayoutParams {
public LayoutParams(Spec rowSpec, Spec columnSpec) {
super(rowSpec, columnSpec);
}
public LayoutParams() {
super();
}
public LayoutParams(ViewGroup.LayoutParams params) {
super(params);
}
public LayoutParams(MarginLayoutParams params) {
super(params);
}
public LayoutParams(GridLayout.LayoutParams source) {
super(source);
}
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void setBaseAttributes(TypedArray a,
int widthAttr, int heightAttr) {
if (a.hasValue(widthAttr)) {
width = a.getLayoutDimension(widthAttr, "layout_width");
} else {
width = WRAP_CONTENT;
}
if (a.hasValue(heightAttr)) {
height = a.getLayoutDimension(heightAttr, "layout_height");
} else {
height = WRAP_CONTENT;
}
}
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mProtectFromCheckedChange) {
return;
}
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
int id = buttonView.getId();
setCheckedId(id);
}
}
private class PassThroughHierarchyChangeListener implements
ViewGroup.OnHierarchyChangeListener {
private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
#Override
public void onChildViewAdded(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
int id = child.getId();
if (id == View.NO_ID) {
id = View.generateViewId();
child.setId(id);
}
((RadioButton) child).setOnCheckedChangeListener(
mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
#Override
public void onChildViewRemoved(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
((RadioButton) child).setOnCheckedChangeListener(null);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
}
#Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
}
}
#Override
public void autofill(AutofillValue value) {
if (!isEnabled()) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!value.isList()) {
Timber.w(value + " could not be autofilled into " + this);
return;
}
}
int index = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
index = value.getListValue();
}
final View child = getChildAt(index);
if (child == null) {
Timber.w("RadioGroup.autoFill(): no child with index %s", index);
return;
}
check(child.getId());
}
#Override
public int getAutofillType() {
return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
}
#Override
public AutofillValue getAutofillValue() {
if (!isEnabled()) return null;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getId() == mCheckedId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return AutofillValue.forList(i);
}
}
}
return null;
}
}
create two radio group.one is for first row and other is for second row.then add the following code in your java code
mFirstGroup = (RadioGroup) findViewById(R.id.first_group);
mSecondGroup = (RadioGroup) findViewById(R.id.second_group);
mFirstGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId != -1 && isChecking) {
isChecking = false;
mSecondGroup.clearCheck();
mCheckedId = checkedId;
}
isChecking = true;
}
});
mSecondGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId != -1 && isChecking) {
isChecking = false;
mFirstGroup.clearCheck();
mCheckedId = checkedId;
}
isChecking = true;
}
});
One possible solution is described by #Suhail k k.
Also have a look here (just more details to answer of #Suhail k k.).
I can propose another option:
1) make you own views (ImageView for example) and place them as you wish in your layout; put android:tag on each of them (serial number, for example, from 0 to 7);
2) make selector for each of them (state normal/selected);
3) at runtime put onClickListener on these items like this:
#Override
public void onClick(View v) {
images.get(currentSelected).setSelected(false);
currentSelected = (int) v.getTag();
images.get(currentSelected).setSelected(true);
}
It would be much easier for you to implement, imho.
Hope you got an idea in total, your implementation might be different :)
The MyViewPager have to be vertical scrolled when the user make scroll inside the pager.
This was working in android version 19, right now I have updated the android version to v21 and what I get is a the refresh ball over the pager. I can make invisible the ball but the pager still without scroll.
This is my main-content.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.widget.SwipeRefreshLayout
android:layout_below="#id/pull_text_layout"
android:id="#+id/refresh"
android:layout_width="match_parent"
android:layout_height="205dp">
<com.pager.MyViewPager
android:id="#+id/pager"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
</com.pager.MyViewPager>
</android.support.v4.widget.SwipeRefreshLayout>
And this is MyActivity.java
// Pager
mPager = (MyViewPager) findViewById(R.id.pager);
mPagerAdapter = new CardsViewPagerAdapter(this, cardResourceIds, cardBackResourceIds);
mPager.setAdapter(mPagerAdapter);
mPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(final int position) {
updateToCard(position);
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(Delays.DELAY_BALANCE);
mPagerAdapter.updateBalance(position, cardBalances[mRandom.nextInt(2)]);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
mPager.setListener(new MyViewPager.ScrollListener() {
#Override
public void onScrollStarted() {
mRefresh.setEnabled(false);
}
#Override
public void onScrollFinished() {
mRefresh.setEnabled(true);
}
});
mRefresh = (SwipeRefreshLayout) findViewById(R.id.refresh);
mRefresh.setColorScheme(android.R.color.transparent, android.R.color.transparent,
android.R.color.transparent, android.R.color.transparent);
mRefresh.setOnRefreshListener(new OnRefreshListener() {
#Override
public void onRefresh() {
mRefresh.setRefreshing(false);
addPaymentFragment(mPager.getCurrentItem() != 3);
}
});
and this is MyViewPager
public class MyViewPager extends ViewPager {
private boolean paginationEnabled = true,
scrolling = false;
private int scrolled;
private ScrollListener listener;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attr) {
super(context, attr);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (!paginationEnabled) {
return false;
} else {
int action = e.getAction();
if (scrolling && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
scrolling = false;
if (listener != null) {
listener.onScrollFinished();
}
if(scrolling)
{}
}
return super.onInterceptTouchEvent(e);
}
}
public void setPaginationEnabled(boolean paginationEnabled) {
this.paginationEnabled = paginationEnabled;
}
public void setListener(ScrollListener listener) {
this.listener = listener;
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
scrolling = true;
if (listener != null) {
listener.onScrollStarted();
}
}
public interface ScrollListener {
public void onScrollStarted();
public void onScrollFinished();
}
}
I am using the DroidParts library for Clearable EditTexts (http://droidparts.org/widgets.html#clearableedittext). The question is how to keep the cross/clear button on the first line. I have no idea where to start looking so any help would be great! Thanks
Code is this:
import static org.droidparts.util.Strings.isNotEmpty;
import org.droidparts.adapter.widget.TextWatcherAdapter;
import org.droidparts.adapter.widget.TextWatcherAdapter.TextWatcherListener;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.widget.EditText;
public class ClearableEditText extends EditText implements OnTouchListener,
OnFocusChangeListener, TextWatcherListener {
public interface Listener {
void didClearText();
}
public void setListener(Listener listener) {
this.listener = listener;
}
private Drawable xD;
private Listener listener;
public ClearableEditText(Context context) {
super(context);
init();
}
public ClearableEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ClearableEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
xD = getCompoundDrawables()[2];
if (xD == null) {
xD = getResources()
.getDrawable(android.R.drawable.presence_offline);
}
xD.setBounds(0, 0, xD.getIntrinsicWidth(), xD.getIntrinsicHeight());
setClearIconVisible(false);
super.setOnTouchListener(this);
super.setOnFocusChangeListener(this);
addTextChangedListener(new TextWatcherAdapter(this, this));
}
#Override
public void setOnTouchListener(OnTouchListener l) {
this.l = l;
}
#Override
public void setOnFocusChangeListener(OnFocusChangeListener f) {
this.f = f;
}
private OnTouchListener l;
private OnFocusChangeListener f;
#Override
public boolean onTouch(View v, MotionEvent event) {
if (getCompoundDrawables()[2] != null) {
if (event.getAction() == MotionEvent.ACTION_UP) {
boolean tappedX = event.getX() > (getWidth()
- getPaddingRight() - xD.getIntrinsicWidth());
if (tappedX) {
setText("");
if (listener != null) {
listener.didClearText();
}
return true;
}
}
}
if (l != null) {
return l.onTouch(v, event);
}
return false;
}
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
setClearIconVisible(isNotEmpty(getText()));
} else {
setClearIconVisible(false);
}
if (f != null) {
f.onFocusChange(v, hasFocus);
}
}
#Override
public void onTextChanged(EditText view, String text) {
if (isFocused()) {
setClearIconVisible(isNotEmpty(text));
}
}
protected void setClearIconVisible(boolean visible) {
Drawable x = visible ? xD : null;
setCompoundDrawables(getCompoundDrawables()[0],
getCompoundDrawables()[1], x, getCompoundDrawables()[3]);
}
}
Is there another method that will have the same effect?