I have created an horizontal recycler view with few items, and I have made it to be scrolled automatically(looped).
if I stop the autoScroll, I can scroll the list horizontally and if I scroll it vertically, it's parent recycler view will be scrolled vertically.
but it the autoscroll is enabled, I can only scroll it horizontally, and if I try to scroll it vertically so it's parent recycler view scrolls, nothing moves, but the horizontal recycler view.
Does anyone have any idea how to make my recycler view to be scrolled horizontally on user touch, and when its vertical, its parent recycler view moved?
here the AutoScrollRecyclerView:
public class AutoScrollRecyclerView extends RecyclerView {
private static final String TAG = AutoScrollRecyclerView.class.getSimpleName();
private static final int SPEED = 10;
/**
* Sliding estimator
*/
private UniformSpeedInterpolator mInterpolator;
/**
* Dx and dy between units
*/
private int mSpeedDx, mSpeedDy;
/**
* Sliding speed, default 100
*/
private int mCurrentSpeed = SPEED;
/**
* Whether to display the list infinitely
*/
private boolean mLoopEnabled;
/**
* Whether to slide backwards
*/
private boolean mReverse;
/**
* Whether to turn on automatic sliding
*/
private boolean mIsOpenAuto;
/**
* Whether the user can manually slide the screen
*/
private boolean mCanTouch = true;
/**
* Whether the user clicks on the screen
*/
private boolean mPointTouch;
/**
* Are you ready for data?
*/
private boolean mReady;
/**
* Whether initialization is complete
*/
private boolean mInflate;
/**
* Whether to stop scroll
*/
private boolean isStopAutoScroll = false;
public AutoScrollRecyclerView(Context context) {
this(context, null);
}
public AutoScrollRecyclerView(Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public AutoScrollRecyclerView(Context context, #Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mInterpolator = new UniformSpeedInterpolator();
mReady = false;
}
/**
* Start sliding
*/
public void startAutoScroll() {
isStopAutoScroll = false;
openAutoScroll(mCurrentSpeed, mReverse);
}
/**
* Start sliding
*
* #param speed Sliding distance (determining the sliding speed)
* #param reverse Whether to slide backwards
*/
public void openAutoScroll(int speed, boolean reverse) {
mReverse = reverse;
mCurrentSpeed = speed;
mIsOpenAuto = true;
notifyLayoutManager();
startScroll();
}
/**
* Is it possible to manually slide when swiping automatically?
*/
public void setCanTouch(boolean b) {
mCanTouch = b;
}
public boolean canTouch() {
return mCanTouch;
}
/**
* Set whether to display the list infinitely
*/
public void setLoopEnabled(boolean loopEnabled) {
this.mLoopEnabled = loopEnabled;
if (getAdapter() != null) {
getAdapter().notifyDataSetChanged();
startScroll();
}
}
/**
* Whether to slide infinitely
*/
public boolean isLoopEnabled() {
return mLoopEnabled;
}
/**
* Set whether to reverse
*/
public void setReverse(boolean reverse) {
mReverse = reverse;
notifyLayoutManager();
startScroll();
}
/**
* #param isStopAutoScroll
*/
public void pauseAutoScroll(boolean isStopAutoScroll) {
this.isStopAutoScroll = isStopAutoScroll;
}
public boolean getReverse() {
return mReverse;
}
/**
* Start scrolling
*/
private void startScroll() {
if (!mIsOpenAuto)
return;
if (getScrollState() == SCROLL_STATE_SETTLING)
return;
if (mInflate && mReady) {
mSpeedDx = mSpeedDy = 0;
smoothScroll();
}
}
private void smoothScroll() {
if (!isStopAutoScroll) {
int absSpeed = Math.abs(mCurrentSpeed);
int d = mReverse ? -absSpeed : absSpeed;
smoothScrollBy(d, d, mInterpolator);
}
}
private void notifyLayoutManager() {
/*LayoutManager layoutManager = getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) layoutManager);
if (linearLayoutManager != null) {
linearLayoutManager.setReverseLayout(mReverse);
}
} else {
StaggeredGridLayoutManager staggeredGridLayoutManager = ((StaggeredGridLayoutManager) layoutManager);
if (staggeredGridLayoutManager != null) {
staggeredGridLayoutManager.setReverseLayout(mReverse);
}
}*/
}
#Override
public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) {
super.swapAdapter(generateAdapter(adapter), removeAndRecycleExistingViews);
mReady = true;
}
#Override
public void setAdapter(Adapter adapter) {
super.setAdapter(generateAdapter(adapter));
mReady = true;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (mCanTouch) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
mPointTouch = true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (mIsOpenAuto) {
return true;
}
}
return super.onInterceptTouchEvent(e);
} else return true;
}
#Override
public boolean onTouchEvent(MotionEvent e) {
if (mCanTouch) {
switch (e.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mIsOpenAuto) {
mPointTouch = false;
smoothScroll();
return true;
}
}
return super.onTouchEvent(e);
} else return true;
}
#Override
public boolean performClick() {
return super.performClick();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
startScroll();
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mInflate = true;
}
#Override
public void onScrolled(int dx, int dy) {
if (mPointTouch) {
mSpeedDx = 0;
mSpeedDy = 0;
return;
}
boolean vertical;
if (dx == 0) {//Vertical scrolling
mSpeedDy += dy;
vertical = true;
} else {//Horizontal scrolling
mSpeedDx += dx;
vertical = false;
}
if (vertical) {
if (Math.abs(mSpeedDy) >= Math.abs(mCurrentSpeed)) {
mSpeedDy = 0;
smoothScroll();
}
} else {
if (Math.abs(mSpeedDx) >= Math.abs(mCurrentSpeed)) {
mSpeedDx = 0;
smoothScroll();
}
}
}
#NonNull
#SuppressWarnings("unchecked")
private NestingRecyclerViewAdapter generateAdapter(Adapter adapter) {
return new NestingRecyclerViewAdapter(this, adapter);
}
/**
* Custom estimator
* Swipe the list at a constant speed
*/
private static class UniformSpeedInterpolator implements Interpolator {
#Override
public float getInterpolation(float input) {
return input;
}
}
/**
* Customize the Adapter container so that the list can be displayed in an infinite loop
*/
private static class NestingRecyclerViewAdapter<VH extends ViewHolder>
extends Adapter<VH> {
private AutoScrollRecyclerView mRecyclerView;
Adapter<VH> mAdapter;
NestingRecyclerViewAdapter(AutoScrollRecyclerView recyclerView, Adapter<VH> adapter) {
mAdapter = adapter;
mRecyclerView = recyclerView;
}
#NonNull
#Override
public VH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return mAdapter.onCreateViewHolder(parent, viewType);
}
#Override
public void registerAdapterDataObserver(#NonNull AdapterDataObserver observer) {
super.registerAdapterDataObserver(observer);
mAdapter.registerAdapterDataObserver(observer);
}
#Override
public void unregisterAdapterDataObserver(#NonNull AdapterDataObserver observer) {
super.unregisterAdapterDataObserver(observer);
mAdapter.unregisterAdapterDataObserver(observer);
}
#Override
public void onBindViewHolder(#NonNull VH holder, int position) {
mAdapter.onBindViewHolder(holder, generatePosition(position));
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
mAdapter.setHasStableIds(hasStableIds);
}
#Override
public int getItemCount() {
//If it is an infinite scroll mode, set an unlimited number of items
return getLoopEnable() ? Integer.MAX_VALUE : mAdapter.getItemCount();
}
#Override
public int getItemViewType(int position) {
return mAdapter.getItemViewType(generatePosition(position));
}
#Override
public long getItemId(int position) {
return mAdapter.getItemId(generatePosition(position));
}
/**
* Returns the corresponding position according to the current scroll mode
*/
private int generatePosition(int position) {
if (getLoopEnable()) {
return getActualPosition(position);
} else {
return position;
}
}
/**
* Returns the actual position of the item
*
* #param position The position after starting to scroll will grow indefinitely
* #return Item actual location
*/
private int getActualPosition(int position) {
int itemCount = mAdapter.getItemCount();
return position >= itemCount && itemCount > 0 ? position % itemCount : position;
}
private boolean getLoopEnable() {
return mRecyclerView.mLoopEnabled;
}
public boolean getReverse() {
return mRecyclerView.mReverse;
}
}
}
Related
I am using PullToRefreshListView to provide data reload when pulling the listview.
But my problem is that after refreshing, the layout leaves a space on top of the listview. See the image below:
I want to remove the space on top. I tried setting the view to View.GONE but it still leaves a small space in it.
Here's the code for the PullToRefreshListView.java:
package com.markupartist.android.widget;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
public class PullToRefreshListView extends ListView implements OnScrollListener {
private static final int TAP_TO_REFRESH = 1;
private static final int PULL_TO_REFRESH = 2;
private static final int RELEASE_TO_REFRESH = 3;
private static final int REFRESHING = 4;
private static final String TAG = "PullToRefreshListView";
private OnRefreshListener mOnRefreshListener;
/**
* Listener that will receive notifications every time the list scrolls.
*/
private OnScrollListener mOnScrollListener;
private LayoutInflater mInflater;
private RelativeLayout mRefreshView;
private TextView mRefreshViewText;
private ImageView mRefreshViewImage;
private ProgressBar mRefreshViewProgress;
private TextView mRefreshViewLastUpdated;
private int mCurrentScrollState;
private int mRefreshState;
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
private int mRefreshViewHeight;
private int mRefreshOriginalTopPadding;
private int mLastMotionY;
private boolean mBounceHack;
public PullToRefreshListView(Context context) {
super(context);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
// Load all of the animations we need in code rather than through XML
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setInterpolator(new LinearInterpolator());
mFlipAnimation.setDuration(250);
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration(250);
mReverseFlipAnimation.setFillAfter(true);
mInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mRefreshView = (RelativeLayout) mInflater.inflate(
R.layout.pull_to_refresh_header, this, false);
mRefreshViewText =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
mRefreshViewImage =
(ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
mRefreshViewProgress =
(ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
mRefreshViewLastUpdated =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);
mRefreshViewImage.setMinimumHeight(50);
mRefreshView.setOnClickListener(new OnClickRefreshListener());
mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();
mRefreshState = TAP_TO_REFRESH;
addHeaderView(mRefreshView);
super.setOnScrollListener(this);
measureView(mRefreshView);
mRefreshViewHeight = mRefreshView.getMeasuredHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelection(1);
}
#Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
setSelection(1);
}
/**
* Set the listener that will receive notifications every time the list
* scrolls.
*
* #param l The scroll listener.
*/
#Override
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener = l;
}
/**
* Register a callback to be invoked when this list should be refreshed.
*
* #param onRefreshListener The callback to run.
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
mOnRefreshListener = onRefreshListener;
}
/**
* Set a text to represent when the list was last updated.
* #param lastUpdated Last updated at.
*/
public void setLastUpdated(CharSequence lastUpdated) {
if (lastUpdated != null) {
mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
mRefreshViewLastUpdated.setText(lastUpdated);
} else {
mRefreshViewLastUpdated.setVisibility(View.GONE);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int y = (int) event.getY();
mBounceHack = false;
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
if ((mRefreshView.getBottom() >= mRefreshViewHeight
|| mRefreshView.getTop() >= 0)
&& mRefreshState == RELEASE_TO_REFRESH) {
// Initiate the refresh
mRefreshState = REFRESHING;
prepareForRefresh();
onRefresh();
} else if (mRefreshView.getBottom() < mRefreshViewHeight
|| mRefreshView.getTop() <= 0) {
// Abort refresh and scroll down below the refresh view
resetHeader();
setSelection(1);
}
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
applyHeaderPadding(event);
break;
}
return super.onTouchEvent(event);
}
private void applyHeaderPadding(MotionEvent ev) {
// getHistorySize has been available since API 1
int pointerCount = ev.getHistorySize();
for (int p = 0; p < pointerCount; p++) {
if (mRefreshState == RELEASE_TO_REFRESH) {
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
int historicalY = (int) ev.getHistoricalY(p);
// Calculate the padding to apply, we divide by 1.7 to
// simulate a more resistant effect during pull.
int topPadding = (int) (((historicalY - mLastMotionY)
- mRefreshViewHeight) / 1.7);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
topPadding,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
}
}
/**
* Sets the header padding back to original size.
*/
private void resetHeaderPadding() {
Log.i("top padding", "" + mRefreshOriginalTopPadding);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
0,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
/**
* Resets the header to the original state.
*/
private void resetHeader() {
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshState = TAP_TO_REFRESH;
resetHeaderPadding();
// Set refresh view text to the pull label
//mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
//mRefreshViewText.setVisibility(View.GONE);
// Replace refresh drawable with arrow drawable
mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
// Clear the full rotation animation
mRefreshViewImage.clearAnimation();
// Hide progress bar and arrow.
mRefreshViewImage.setVisibility(View.GONE);
mRefreshViewProgress.setVisibility(View.GONE);
//this.setSelectionAfterHeaderView();
}
}
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0,
0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// When the refresh view is completely visible, change the text to say
// "Release to refresh..." and flip the arrow drawable.
if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
&& mRefreshState != REFRESHING) {
if (firstVisibleItem == 0) {
mRefreshViewImage.setVisibility(View.VISIBLE);
if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20
|| mRefreshView.getTop() >= 0)
&& mRefreshState != RELEASE_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mFlipAnimation);
mRefreshState = RELEASE_TO_REFRESH;
} else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
&& mRefreshState != PULL_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mReverseFlipAnimation);
}
mRefreshState = PULL_TO_REFRESH;
}
} else {
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
}
} else if (mCurrentScrollState == SCROLL_STATE_FLING
&& firstVisibleItem == 0
&& mRefreshState != REFRESHING) {
Log.i("I am here", "");
setSelection(1);
mBounceHack = true;
} else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
setSelection(1);
}
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
if (mCurrentScrollState == SCROLL_STATE_IDLE) {
mBounceHack = false;
}
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
public void prepareForRefresh() {
resetHeaderPadding();
mRefreshViewImage.setVisibility(View.GONE);
// We need this hack, otherwise it will keep the previous drawable.
mRefreshViewImage.setImageDrawable(null);
mRefreshViewProgress.setVisibility(View.VISIBLE);
// Set refresh view text to the refreshing label
mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
mRefreshState = REFRESHING;
}
public void onRefresh() {
Log.d(TAG, "onRefresh");
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
/**
* Resets the list to a normal state after a refresh.
* #param lastUpdated Last updated at.
*/
public void onRefreshComplete(CharSequence lastUpdated) {
setLastUpdated(lastUpdated);
onRefreshComplete();
}
/**
* Resets the list to a normal state after a refresh.
*/
public void onRefreshComplete() {
Log.d(TAG, "onRefreshComplete");
resetHeader();
// If refresh view is visible when loading completes, scroll down to
// the next item.
if (getFirstVisiblePosition() == 0) {
invalidateViews();
setSelection(1);
}
resetHeader();
}
/**
* Invoked when the refresh view is clicked on. This is mainly used when
* there's only a few items in the list and it's not possible to drag the
* list.
*/
private class OnClickRefreshListener implements OnClickListener {
#Override
public void onClick(View v) {
if (mRefreshState != REFRESHING) {
prepareForRefresh();
onRefresh();
}
}
}
/**
* Interface definition for a callback to be invoked when list should be
* refreshed.
*/
public interface OnRefreshListener {
/**
* Called when the list should be refreshed.
* <p>
* A call to {#link PullToRefreshListView #onRefreshComplete()} is
* expected to indicate that the refresh has completed.
*/
public void onRefresh();
}
}
I would suggest you to Just disable listview onrefresh listener and
use android.support.v4.widget.SwipeRefreshLayout instead of pull to refresh listview . It is very easy to use.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refreshLater"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
***Place Your listview here***
</android.support.v4.widget.SwipeRefreshLayout >
you can set refresh listener on it like this:
public SwipeRefreshLayout swipeRefreshLayout;
swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.refreshLater);
swipeRefreshLayout.setOnRefreshListener(this);
you can do needed code in the below override method:
#Override
public void onRefresh()
{
swipeRefreshLayout.setRefreshing(false);
}
I am trying to implement tabs into my application and I have added the SlidingTabLayout.java and SlidingTabStrip.java from Google. I also made sure to add the setDistributeEvenly method within the SlidingTabLayout class.
My problem is coming from the R.attr.colorForeground. I am getting the error 'Cannot resolve sysmbol 'colorForeground'.
Here is the the two classes for which these are made for the tabs.
class SlidingTabStrip extends LinearLayout {
private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0;
private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3;
private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
private final int mBottomBorderThickness;
private final Paint mBottomBorderPaint;
private final int mSelectedIndicatorThickness;
private final Paint mSelectedIndicatorPaint;
private final int mDefaultBottomBorderColor;
private final SimpleTabColorizer mDefaultTabColorizer;
private int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout.TabColorizer mCustomTabColorizer;
SlidingTabStrip(Context context) {
this(context, null);
}
SlidingTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
final float density = getResources().getDisplayMetrics().density;
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
final int themeForegroundColor = outValue.data;
mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
mDefaultTabColorizer = new SimpleTabColorizer();
mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
mBottomBorderPaint = new Paint();
mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
mSelectedIndicatorPaint = new Paint();
}
/**
* Set the alpha value of the {#code color} to be the given {#code alpha} value.
*/
private static int setColorAlpha(int color, byte alpha) {
return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
}
/**
* Blend {#code color1} and {#code color2} using the given ratio.
*
* #param ratio of which to blend. 1.0 will return {#code color1}, 0.5 will give an even blend,
* 0.0 will return {#code color2}.
*/
private static int blendColors(int color1, int color2, float ratio) {
final float inverseRation = 1f - ratio;
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
return Color.rgb((int) r, (int) g, (int) b);
}
void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
mCustomTabColorizer = customTabColorizer;
invalidate();
}
void setSelectedIndicatorColors(int... colors) {
// Make sure that the custom colorizer is removed
mCustomTabColorizer = null;
mDefaultTabColorizer.setIndicatorColors(colors);
invalidate();
}
void onViewPagerPageChanged(int position, float positionOffset) {
mSelectedPosition = position;
mSelectionOffset = positionOffset;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
final int height = getHeight();
final int childCount = getChildCount();
final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
? mCustomTabColorizer
: mDefaultTabColorizer;
// Thick colored underline below the current selection
if (childCount > 0) {
View selectedTitle = getChildAt(mSelectedPosition);
int left = selectedTitle.getLeft();
int right = selectedTitle.getRight();
int color = tabColorizer.getIndicatorColor(mSelectedPosition);
if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
if (color != nextColor) {
color = blendColors(nextColor, color, mSelectionOffset);
}
// Draw the selection partway between the tabs
View nextTitle = getChildAt(mSelectedPosition + 1);
left = (int) (mSelectionOffset * nextTitle.getLeft() +
(1.0f - mSelectionOffset) * left);
right = (int) (mSelectionOffset * nextTitle.getRight() +
(1.0f - mSelectionOffset) * right);
}
mSelectedIndicatorPaint.setColor(color);
canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
height, mSelectedIndicatorPaint);
}
// Thin underline along the entire bottom edge
canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
}
private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
private int[] mIndicatorColors;
#Override
public final int getIndicatorColor(int position) {
return mIndicatorColors[position % mIndicatorColors.length];
}
void setIndicatorColors(int... colors) {
mIndicatorColors = colors;
}
}
}
public class SlidingTabLayout extends HorizontalScrollView {
private static final int TITLE_OFFSET_DIPS = 24;
private static final int TAB_VIEW_PADDING_DIPS = 16;
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
private final SlidingTabStrip mTabStrip;
private int mTitleOffset;
private int mTabViewLayoutId;
private int mTabViewTextViewId;
private boolean mDistributeEvenly;
private ViewPager mViewPager;
private SparseArray<String> mContentDescriptions = new SparseArray<String>();
private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
public SlidingTabLayout(Context context) {
this(context, null);
}
public SlidingTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Disable the Scroll Bar
setHorizontalScrollBarEnabled(false);
// Make sure that the Tab Strips fills this View
setFillViewport(true);
mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
/**
* Set the custom {#link TabColorizer} to be used.
* <p/>
* If you only require simple custmisation then you can use
* {#link #setSelectedIndicatorColors(int...)} to achieve
* similar effects.
*/
public void setCustomTabColorizer(TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
/**
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
* circular array. Providing one color will mean that all tabs are indicated with the same color.
*/
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
/**
* Set the {#link ViewPager.OnPageChangeListener}. When using {#link SlidingTabLayout} you are
* required to set any {#link ViewPager.OnPageChangeListener} through this method. This is so
* that the layout can update it's scroll position correctly.
*
* #see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
*/
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
/**
* Set the custom layout to be inflated for the tab views.
*
* #param layoutResId Layout id to be inflated
* #param textViewId id of the {#link TextView} in the inflated view
*/
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
/**
* Sets the associated view pager. Note that the assumption here is that the pager content
* (number of tabs and tab titles) does not change after this call has been made.
*/
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.setOnPageChangeListener(new InternalViewPagerListener());
populateTabStrip();
}
}
/**
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
* {#link #setCustomTabView(int, int)}.
*/
protected TextView createDefaultTabView(Context context) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
outValue, true);
textView.setBackgroundResource(outValue.resourceId);
textView.setAllCaps(true);
int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new TabClickListener();
for (int i = 0; i < adapter.getCount(); i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
// If there is a custom tab view layout id set, try and inflate it
tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
false);
tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
}
if (tabView == null) {
tabView = createDefaultTabView(getContext());
}
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
tabTitleView = (TextView) tabView;
}
if (mDistributeEvenly) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
}
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
}
}
public void setContentDescription(int i, String desc) {
mContentDescriptions.put(i, desc);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mViewPager != null) {
scrollToTab(mViewPager.getCurrentItem(), 0);
}
}
private void scrollToTab(int tabIndex, int positionOffset) {
final int tabStripChildCount = mTabStrip.getChildCount();
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
return;
}
View selectedChild = mTabStrip.getChildAt(tabIndex);
if (selectedChild != null) {
int targetScrollX = selectedChild.getLeft() + positionOffset;
if (tabIndex > 0 || positionOffset > 0) {
// If we're not at the first child and are mid-scroll, make sure we obey the offset
targetScrollX -= mTitleOffset;
}
scrollTo(targetScrollX, 0);
}
}
/**
* Allows complete control over the colors drawn in the tab layout. Set with
* {#link #setCustomTabColorizer(TabColorizer)}.
*/
public interface TabColorizer {
/**
* #return return the color of the indicator used when {#code position} is selected.
*/
int getIndicatorColor(int position);
}
private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
private int mScrollState;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int tabStripChildCount = mTabStrip.getChildCount();
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
return;
}
mTabStrip.onViewPagerPageChanged(position, positionOffset);
View selectedTitle = mTabStrip.getChildAt(position);
int extraOffset = (selectedTitle != null)
? (int) (positionOffset * selectedTitle.getWidth())
: 0;
scrollToTab(position, extraOffset);
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mTabStrip.onViewPagerPageChanged(position, 0f);
scrollToTab(position, 0);
}
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
mTabStrip.getChildAt(i).setSelected(position == i);
}
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageSelected(position);
}
}
}
private class TabClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
return;
}
}
}
}
}
On both classes from google they have no declared the colorForeground so I am assuming it is set into Android? Any help would be greatly appreciated on fixing this issue with the colorForeground.
It is because android is not able to find R.attr.colorForeground since you (just as I did once) imported your own R into SlidingTabStrip. It is better to import import android.R; (Android Studio warns not to, tho) or use android.R.attr.colorForeground directly.
There is a difference between:
android.R;
is used for accessing public standard android SDK resources.
and
com.yourpackage.R;
is used for accessing YOUR resources in your application.
You can use both, but if you are using your R reference, you MUST explicitly resolve either depending on where/what you need
Remove your own package say ex: com.yourpackage.R.
Place android.R.attr.colorForeground instead of R.attr.colorForeground
I am having nearly 500+ images in Imageview inside Horizontalscrollview. If i am selecting an image then I am marking it as selected. If I am selecting any other images in the view, it should be un-select and newly clicked image should have to be selected. How could I can achieve it?
for (int i = 0; i < Home.arr_category_item_list.size(); i++) {
ImageView circleImageView = new ImageView(getActivity());
imageLoader.get(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_IMAGE), ImageLoader.getImageListener(circleImageView, R.drawable.defaultimage, R.drawable.defaultimage));
circleImageView.setTag(Integer.parseInt(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_ID)));
circleImageView.setLayoutParams(params);
lnr_category_item.addView(circleImageView);
}
Please check the image attached. At the bottom of the screen there is an Image view. So user will have option to select only one image at a time.
Now this is some really old code, hope it still works.
Note: there may be a thing or two missing, but you can get the idea from this implementation
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import yourpackage.R;
//Creataed by Bojan Kseneman on 14.8.2013
public class CustomCheckBox extends ImageView {
private boolean isChecked;
private boolean isImageShown;
private boolean useCustomClickListener;
//private String android_xmlns = "http://schemas.android.com/apk/res/android";
private String app_xmlns;
private int checkboxOnResID;
private int checkboxOffResID;
private int checkboxDisabledOnResID;
private int checkboxDisabledOffResID;
//private int imageHeight;
//private int imageWidth;
public CustomCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
app_xmlns = new StringBuilder("http://schemas.android.com/apk/res/" + context.getPackageName()).toString();
init(attrs);
}
private void init(AttributeSet attrs) {
checkboxOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceChecked", R.drawable.round_checkbox_on);
checkboxOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceNotChecked", R.drawable.round_checkbox_off);
checkboxDisabledOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOn", R.drawable.round_checkbox_off);
checkboxDisabledOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOff", R.drawable.round_checkbox_off);
useCustomClickListener = attrs.getAttributeBooleanValue(app_xmlns, "customClickEvent", false);
if (useCustomClickListener)
this.setOnTouchListener(new CboxTouchListener());
else {
this.setOnTouchListener(new NormalClickListener());
}
if (!hasOnClickListener()) {
/**
* assign a new onClick listener so we get desired onClick sound
* effect (because we call it) this is opposite to how android
* behaves, where you don't hear the sound if there is not
* onClickListener assigned
*/
this.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
private boolean hasOnClickListener() {
try {
if (android.os.Build.VERSION.SDK_INT >= 14) {
//the information is inside ListenerInfo
java.lang.reflect.Field listenerInfoField = null;
listenerInfoField = Class.forName("android.view.View").getDeclaredField("mListenerInfo");
if (listenerInfoField != null)
listenerInfoField.setAccessible(true);
Object mOnClickListener = null;
mOnClickListener = listenerInfoField.get(this); //get from view object, in this case this is this
// get the field mOnClickListener, that holds the listener and cast it to a listener
java.lang.reflect.Field listenerField = null;
listenerField = Class.forName("android.view.View$ListenerInfo").getDeclaredField("mOnClickListener");
//View.OnClickListener myListener = (View.OnClickListener) listenerField.get(myLiObject);
return (listenerField.get(mOnClickListener) != null);
}
else {
//directly in View
java.lang.reflect.Field f = Class.forName("android.view.View").getDeclaredField("mOnClickListener");
return (f.get(this) != null);
}
}
catch (Exception e) {
return false;
}
}
// private void setScaledDownImage(int resID) {
// this.setImageBitmap(CommonMethods.decodeSampledBitmapFromResource(getContext(), resID, imageWidth, imageHeight));
// }
public boolean isChecked() {
return (isChecked && this.isEnabled());
}
public void setChecked(boolean isChecked) {
if (this.isEnabled())
setCheckedIgnoreEnabled(isChecked);
else
this.setEnabled(false);
}
public void setCheckedIgnoreEnabled(boolean isChecked) {
if ((this.isChecked != isChecked) || !isImageShown) {
this.isChecked = isChecked;
if (isChecked)
setImageResource(checkboxOnResID);
else
setImageResource(checkboxOffResID);
}
}
#Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled)
setChecked(isChecked);
else {
int resID = isChecked ? checkboxDisabledOnResID : checkboxDisabledOffResID;
setImageResource(resID);
}
}
public void setCheckedAndEnabled(boolean isChecked, boolean isEnabled) {
setCheckedIgnoreEnabled(isChecked);
setEnabled(isEnabled);
}
public void toggle() {
setChecked(!isChecked);
}
public void toggleWithClick() {
toggle();
this.performClick();
}
public void toggleWithSilentClick() {
//v.playSoundEffect(android.view.SoundEffectConstants.CLICK);
boolean currentState = this.isSoundEffectsEnabled();
this.setSoundEffectsEnabled(false);
toggleWithClick();
this.setSoundEffectsEnabled(currentState);
}
private class CboxTouchListener extends ImageBoundClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
private class NormalClickListener extends MyOnClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//this.imageWidth = MeasureSpec.getSize(widthMeasureSpec);
//this.imageHeight = MeasureSpec.getSize(heightMeasureSpec);
if (!isImageShown) {
setChecked(isChecked);
isImageShown = !isImageShown;
}
}
}
I used this click listener, since I was using some round images and I didn't want to trigger the click events when the user clicked on the transparent part of the image.
public abstract class ImageBoundClickListener implements android.view.View.OnTouchListener {
private String TAG = "ImageBoundsTouchListener";
private boolean shouldTriggerAction = false;
Rect allowedArea;
#Override
public boolean onTouch(View v, MotionEvent event) {
//let's us detect only clicks on the part where actual image is and not where the ImageView is
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
float[] eventXY = new float[] { event.getX(), event.getY() };
allowedArea = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
android.graphics.Matrix invertMatrix = new android.graphics.Matrix();
ImageView iv = (ImageView) v;
iv.getImageMatrix().invert(invertMatrix);
invertMatrix.mapPoints(eventXY);
int x = (int) eventXY[0];
int y = (int) eventXY[1];
Drawable imgDrawable = iv.getDrawable();
Bitmap bitmap = ((BitmapDrawable) imgDrawable).getBitmap();
//Limit x,y within the bitmap
if (x < 0)
x = 0;
else if (x > (bitmap.getWidth() - 1))
x = bitmap.getWidth() - 1;
if (y < 0)
y = 0;
else if (y > bitmap.getHeight() - 1)
y = bitmap.getHeight() - 1;
int touchedRGB = bitmap.getPixel(x, y);
//is transparent?
shouldTriggerAction = (touchedRGB == 0) ? false : true;
return true;
case MotionEvent.ACTION_MOVE:
if (!allowedArea.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY()))
//the user went out of the user area
shouldTriggerAction = false;
return true;
case MotionEvent.ACTION_UP:
//finger is no longer on screen
if (shouldTriggerAction)
doSomething();
return true;
default:
return false;
}
}
public void doSomething() {
}
}
I have a listview in my app that uses the drag and drop functionality from this Google video: https://www.youtube.com/watch?v=_BZIvjMgH-Q . It works just fine when the app loads items from the database, but when I trying adding an item to the listview it breaks. Here is what that looks like: https://www.youtube.com/watch?v=_BZIvjMgH-Q
I think the problem is with my getItemId method inside my ItemsArrayAdapter.java class:
#Override
public long getItemId(int position) {
Long idToReturn = (long) INVALID_ID;
if (position >= 0 && position <= mIdMap.size()-1) {
try {
String item = getItem(position);
idToReturn = (long) mIdMap.get(item);
}
catch(Exception e){}
}
return idToReturn;
}
Here is what the DynamicListView.java looks like:
public class DynamicListView extends ListView {
final static String TAG = DynamicListView.class.getSimpleName();
private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
private final int MOVE_DURATION = 150;
private final int LINE_THICKNESS = 15;
public ArrayList<String> mCheeseList;
private int mLastEventY = -1;
private int mDownY = -1;
private int mDownX = -1;
private int mTotalOffset = 0;
private boolean mCellIsMobile = false;
private boolean mIsMobileScrolling = false;
private int mSmoothScrollAmountAtEdge = 0;
private final int INVALID_ID = -1;
private long mAboveItemId = INVALID_ID;
private long mMobileItemId = INVALID_ID;
private long mBelowItemId = INVALID_ID;
private BitmapDrawable mHoverCell;
private Rect mHoverCellCurrentBounds;
private Rect mHoverCellOriginalBounds;
private final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private boolean mIsWaitingForScrollFinish = false;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
public DynamicListView(Context context) {
super(context);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context) {
setOnItemLongClickListener(mOnItemLongClickListener);
setOnScrollListener(mScrollListener);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mSmoothScrollAmountAtEdge = (int)(SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
}
/**
* Listens for long clicks on any mItems in the listview. When a cell has
* been selected, the hover cell is created and set up.
*/
private OnItemLongClickListener mOnItemLongClickListener =
new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) {
mTotalOffset = 0;
int position = pointToPosition(mDownX, mDownY);
int itemNum = position - getFirstVisiblePosition();
View selectedView = getChildAt(itemNum);
mMobileItemId = getAdapter().getItemId(position);
mHoverCell = getAndAddHoverView(selectedView);
selectedView.setVisibility(INVISIBLE);
mCellIsMobile = true;
updateNeighborViewsForID(mMobileItemId);
return true;
}
};
/**
* Creates the hover cell with the appropriate bitmap and of appropriate
* size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
* single time an invalidate call is made.
*/
private BitmapDrawable getAndAddHoverView(View v) {
int w = v.getWidth();
int h = v.getHeight();
int top = v.getTop();
int left = v.getLeft();
Bitmap b = getBitmapWithBorder(v);
BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
drawable.setBounds(mHoverCellCurrentBounds);
return drawable;
}
/** Draws a black border over the screenshot of the view passed in. */
private Bitmap getBitmapWithBorder(View v) {
Bitmap bitmap = getBitmapFromView(v);
Canvas can = new Canvas(bitmap);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(LINE_THICKNESS);
paint.setColor(Color.BLACK);
can.drawBitmap(bitmap, 0, 0, null);
can.drawRect(rect, paint);
return bitmap;
}
/** Returns a bitmap showing a screenshot of the view passed in. */
private Bitmap getBitmapFromView(View v) {
Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas (bitmap);
v.draw(canvas);
return bitmap;
}
/**
* Stores a reference to the views above and below the item currently
* corresponding to the hover cell. It is important to note that if this
* item is either at the top or bottom of the list, mAboveItemId or mBelowItemId
* may be invalid.
*/
private void updateNeighborViewsForID(long itemID) {
int position = getPositionForID(itemID);
ItemsArrayAdapter adapter = ((ItemsArrayAdapter)getAdapter());
mAboveItemId = adapter.getItemId(position - 1);
mBelowItemId = adapter.getItemId(position + 1);
}
/** Retrieves the view in the list corresponding to itemID */
public View getViewForID (long itemID) {
int firstVisiblePosition = getFirstVisiblePosition();
ItemsArrayAdapter adapter = ((ItemsArrayAdapter)getAdapter());
for(int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
int position = firstVisiblePosition + i;
long id = adapter.getItemId(position);
if (id == itemID) {
return v;
}
}
return null;
}
/** Retrieves the position in the list corresponding to itemID */
public int getPositionForID (long itemID) {
View v = getViewForID(itemID);
if (v == null) {
return -1;
} else {
return getPositionForView(v);
}
}
/**
* dispatchDraw gets invoked when all the child views are about to be drawn.
* By overriding this method, the hover cell (BitmapDrawable) can be drawn
* over the listview's mItems whenever the listview is redrawn.
*/
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHoverCell != null) {
mHoverCell.draw(canvas);
}
}
#Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = (int)event.getX();
mDownY = (int)event.getY();
mActivePointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER_ID) {
break;
}
int pointerIndex = event.findPointerIndex(mActivePointerId);
mLastEventY = (int) event.getY(pointerIndex);
int deltaY = mLastEventY - mDownY;
if (mCellIsMobile) {
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
mHoverCell.setBounds(mHoverCellCurrentBounds);
invalidate();
handleCellSwitch();
mIsMobileScrolling = false;
handleMobileCellScroll();
return false;
}
break;
case MotionEvent.ACTION_UP:
touchEventsEnded();
break;
case MotionEvent.ACTION_CANCEL:
touchEventsCancelled();
break;
case MotionEvent.ACTION_POINTER_UP:
/* If a multitouch event took place and the original touch dictating
* the movement of the hover cell has ended, then the dragging event
* ends and the hover cell is animated to its corresponding position
* in the listview. */
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
touchEventsEnded();
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
/**
* This method determines whether the hover cell has been shifted far enough
* to invoke a cell swap. If so, then the respective cell swap candidate is
* determined and the data set is changed. Upon posting a notification of the
* data set change, a layout is invoked to place the cells in the right place.
* Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can
* offset the cell being swapped to where it previously was and then animate it to
* its new position.
*/
private void handleCellSwitch() {
final int deltaY = mLastEventY - mDownY;
int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
View belowView = getViewForID(mBelowItemId);
View mobileView = getViewForID(mMobileItemId);
View aboveView = getViewForID(mAboveItemId);
boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());
if (isBelow || isAbove) {
final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
View switchView = isBelow ? belowView : aboveView;
final int originalItem = getPositionForView(mobileView);
if (switchView == null) {
updateNeighborViewsForID(mMobileItemId);
return;
}
swapElements(mCheeseList, originalItem, getPositionForView(switchView));
((BaseAdapter) getAdapter()).notifyDataSetChanged();
mDownY = mLastEventY;
final int switchViewStartTop = switchView.getTop();
if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT){
mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
} else{
mobileView.setVisibility(View.INVISIBLE);
switchView.setVisibility(View.VISIBLE);
}
updateNeighborViewsForID(mMobileItemId);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
View switchView = getViewForID(switchItemID);
mTotalOffset += deltaY;
int switchViewNewTop = switchView.getTop();
int delta = switchViewStartTop - switchViewNewTop;
switchView.setTranslationY(delta);
ObjectAnimator animator = ObjectAnimator.ofFloat(switchView,
View.TRANSLATION_Y, 0);
animator.setDuration(MOVE_DURATION);
animator.start();
return true;
}
});
}
}
private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) {
Object temp = arrayList.get(indexOne);
arrayList.set(indexOne, arrayList.get(indexTwo));
arrayList.set(indexTwo, temp);
}
/**
* Resets all the appropriate fields to a default state while also animating
* the hover cell back to its correct location.
*/
private void touchEventsEnded () {
final View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile|| mIsWaitingForScrollFinish) {
mCellIsMobile = false;
mIsWaitingForScrollFinish = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
// If the autoscroller has not completed scrolling, we need to wait for it to
// finish in order to determine the final location of where the hover cell
// should be animated to.
if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
mIsWaitingForScrollFinish = true;
return;
}
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());
ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
sBoundEvaluator, mHoverCellCurrentBounds);
hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
});
hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
setEnabled(false);
}
#Override
public void onAnimationEnd(Animator animation) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
setEnabled(true);
invalidate();
}
});
hoverViewAnimator.start();
} else {
touchEventsCancelled();
}
}
/**
* Resets all the appropriate fields to a default state.
*/
private void touchEventsCancelled () {
View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
invalidate();
}
mCellIsMobile = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
}
/**
* This TypeEvaluator is used to animate the BitmapDrawable back to its
* final location when the user lifts his finger by modifying the
* BitmapDrawable's bounds.
*/
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
return new Rect(interpolate(startValue.left, endValue.left, fraction),
interpolate(startValue.top, endValue.top, fraction),
interpolate(startValue.right, endValue.right, fraction),
interpolate(startValue.bottom, endValue.bottom, fraction));
}
public int interpolate(int start, int end, float fraction) {
return (int)(start + fraction * (end - start));
}
};
/**
* Determines whether this listview is in a scrolling state invoked
* by the fact that the hover cell is out of the bounds of the listview;
*/
private void handleMobileCellScroll() {
mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
}
/**
* This method is in charge of determining if the hover cell is above
* or below the bounds of the listview. If so, the listview does an appropriate
* upward or downward smooth scroll so as to reveal new mItems.
*/
public boolean handleMobileCellScroll(Rect r) {
int offset = computeVerticalScrollOffset();
int height = getHeight();
int extent = computeVerticalScrollExtent();
int range = computeVerticalScrollRange();
int hoverViewTop = r.top;
int hoverHeight = r.height();
if (hoverViewTop <= 0 && offset > 0) {
smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
return true;
}
if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
return true;
}
return false;
}
public void setCheeseList(ArrayList<String> cheeseList) {
mCheeseList = cheeseList;
}
/**
* This scroll listener is added to the listview in order to handle cell swapping
* when the cell is either at the top or bottom edge of the listview. If the hover
* cell is at either edge of the listview, the listview will begin scrolling. As
* scrolling takes place, the listview continuously checks if new cells became visible
* and determines whether they are potential candidates for a cell swap.
*/
private OnScrollListener mScrollListener = new OnScrollListener () {
private int mPreviousFirstVisibleItem = -1;
private int mPreviousVisibleItemCount = -1;
private int mCurrentFirstVisibleItem;
private int mCurrentVisibleItemCount;
private int mCurrentScrollState;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
mCurrentFirstVisibleItem = firstVisibleItem;
mCurrentVisibleItemCount = visibleItemCount;
mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
: mPreviousFirstVisibleItem;
mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
: mPreviousVisibleItemCount;
checkAndHandleFirstVisibleCellChange();
checkAndHandleLastVisibleCellChange();
mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
mPreviousVisibleItemCount = mCurrentVisibleItemCount;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
mScrollState = scrollState;
isScrollCompleted();
}
/**
* This method is in charge of invoking 1 of 2 actions. Firstly, if the listview
* is in a state of scrolling invoked by the hover cell being outside the bounds
* of the listview, then this scrolling event is continued. Secondly, if the hover
* cell has already been released, this invokes the animation for the hover cell
* to return to its correct position after the listview has entered an idle scroll
* state.
*/
private void isScrollCompleted() {
if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
if (mCellIsMobile && mIsMobileScrolling) {
handleMobileCellScroll();
} else if (mIsWaitingForScrollFinish) {
touchEventsEnded();
}
}
}
/**
* Determines if the listview scrolled up enough to reveal a new cell at the
* top of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleFirstVisibleCellChange() {
if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
/**
* Determines if the listview scrolled down enough to reveal a new cell at the
* bottom of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleLastVisibleCellChange() {
int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
if (currentLastVisibleItem != previousLastVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
};
}
Here is how I add an item to the listview:
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String text = mNewItemText.getText().toString();
if (!mItems.contains(text) && !text.isEmpty()) {
mItems.add(text);
mItemsArrayAdapter.update();
mItemsArrayAdapter.notifyDataSetChanged();
}
else{
Toast.makeText(NoteActivity.this, text + " is already added.", Toast.LENGTH_LONG).show();
}
}
});
Here is the update method:
public void update(){
for (int i = 0; i < mArrayList.size(); ++i) {
mIdMap.put(mArrayList.get(i), i);
}
}
Thanks in advance.
I've just read all questions about this problem at stackoverflow and some forums, but still have no solution. I tried to remove R.java, clear the cache, edit .xml but nothing helps.
Error text:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.easyten.app/com.easyten.app.EasyTenActivity}:
java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.slidingmenu.lib.SlidingMenu ...
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.slidingmenu.lib.SlidingMenu
at com.slidingmenu.lib.app.SlidingActivityHelper.onCreate(SlidingActivityHelper.java:32)
This is the code:
slidingmenumain.xml
<?xml version="1.0" encoding="utf-8"?>
<com.slidingmenu.lib.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/slidingmenumain"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
SlidingActivityHelper.java
package com.slidingmenu.lib.app;
import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import com.slidingmenu.lib.R;
import com.slidingmenu.lib.SlidingMenu;
public class SlidingActivityHelper {
private Activity mActivity;
private SlidingMenu mSlidingMenu;
private View mViewAbove;
private View mViewBehind;
private boolean mBroadcasting = false;
private boolean mOnPostCreateCalled = false;
private boolean mEnableSlide = true;
public SlidingActivityHelper(Activity activity) {
mActivity = activity;
}
public void onCreate(Bundle savedInstanceState) {
mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null);
}
...other code
}
32 line of SlidingActivityHelper.java is mSlidingMenu = (SlidingMenu) LayoutInflater.from(mActivity).inflate(R.layout.slidingmenumain, null);
SlidingMenu.java
package com.slidingmenu.lib;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.slidingmenu.lib.CustomViewAbove.OnPageChangeListener;
public class SlidingMenu extends RelativeLayout {
public static final int TOUCHMODE_MARGIN = 0;
public static final int TOUCHMODE_FULLSCREEN = 1;
private CustomViewAbove mViewAbove;
private CustomViewBehind mViewBehind;
private OnOpenListener mOpenListener;
private OnCloseListener mCloseListener;
//private boolean mSlidingEnabled;
public static void attachSlidingMenu(Activity activity, SlidingMenu sm, boolean slidingTitle) {
if (sm.getParent() != null)
throw new IllegalStateException("SlidingMenu cannot be attached to another view when" +
" calling the static method attachSlidingMenu");
if (slidingTitle) {
// get the window background
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowBackground});
int background = a.getResourceId(0, 0);
// move everything into the SlidingMenu
ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
decor.removeAllViews();
// save ActionBar themes that have transparent assets
decorChild.setBackgroundResource(background);
sm.setContent(decorChild);
decor.addView(sm);
} else {
// take the above view out of
ViewGroup content = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
View above = content.getChildAt(0);
content.removeAllViews();
sm.setContent(above);
content.addView(sm, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
}
public interface OnOpenListener {
public void onOpen();
}
public interface OnOpenedListener {
public void onOpened();
}
public interface OnCloseListener {
public void onClose();
}
public interface OnClosedListener {
public void onClosed();
}
public interface CanvasTransformer {
public void transformCanvas(Canvas canvas, float percentOpen);
}
public SlidingMenu(Context context) {
this(context, null);
}
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mViewBehind = new CustomViewBehind(context);
addView(mViewBehind, behindParams);
LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mViewAbove = new CustomViewAbove(context);
addView(mViewAbove, aboveParams);
// register the CustomViewBehind2 with the CustomViewAbove
mViewAbove.setCustomViewBehind(mViewBehind);
mViewBehind.setCustomViewAbove(mViewAbove);
mViewAbove.setOnPageChangeListener(new OnPageChangeListener() {
public static final int POSITION_OPEN = 0;
public static final int POSITION_CLOSE = 1;
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) { }
public void onPageSelected(int position) {
if (position == POSITION_OPEN && mOpenListener != null) {
mOpenListener.onOpen();
} else if (position == POSITION_CLOSE && mCloseListener != null) {
mCloseListener.onClose();
}
}
});
// now style everything!
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu);
// set the above and behind views if defined in xml
int viewAbove = ta.getResourceId(R.styleable.SlidingMenu_viewAbove, -1);
if (viewAbove != -1)
setContent(viewAbove);
int viewBehind = ta.getResourceId(R.styleable.SlidingMenu_viewBehind, -1);
if (viewBehind != -1)
setMenu(viewBehind);
int touchModeAbove = ta.getInt(R.styleable.SlidingMenu_aboveTouchMode, TOUCHMODE_MARGIN);
setTouchModeAbove(touchModeAbove);
int touchModeBehind = ta.getInt(R.styleable.SlidingMenu_behindTouchMode, TOUCHMODE_MARGIN);
setTouchModeBehind(touchModeBehind);
int offsetBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindOffset, -1);
int widthBehind = (int) ta.getDimension(R.styleable.SlidingMenu_behindWidth, -1);
if (offsetBehind != -1 && widthBehind != -1)
throw new IllegalStateException("Cannot set both behindOffset and behindWidth for a SlidingMenu");
else if (offsetBehind != -1)
setBehindOffset(offsetBehind);
else if (widthBehind != -1)
setBehindWidth(widthBehind);
else
setBehindOffset(0);
float scrollOffsetBehind = ta.getFloat(R.styleable.SlidingMenu_behindScrollScale, 0.33f);
setBehindScrollScale(scrollOffsetBehind);
int shadowRes = ta.getResourceId(R.styleable.SlidingMenu_shadowDrawable, -1);
if (shadowRes != -1) {
setShadowDrawable(shadowRes);
}
int shadowWidth = (int) ta.getDimension(R.styleable.SlidingMenu_shadowWidth, 0);
setShadowWidth(shadowWidth);
boolean fadeEnabled = ta.getBoolean(R.styleable.SlidingMenu_behindFadeEnabled, true);
setFadeEnabled(fadeEnabled);
float fadeDeg = ta.getFloat(R.styleable.SlidingMenu_behindFadeDegree, 0.66f);
setFadeDegree(fadeDeg);
boolean selectorEnabled = ta.getBoolean(R.styleable.SlidingMenu_selectorEnabled, false);
setSelectorEnabled(selectorEnabled);
int selectorRes = ta.getResourceId(R.styleable.SlidingMenu_selectorDrawable, -1);
if (selectorRes != -1)
setSelectorDrawable(selectorRes);
}
public void setContent(int res) {
setContent(LayoutInflater.from(getContext()).inflate(res, null));
}
public void setContent(View v) {
mViewAbove.setContent(v);
mViewAbove.invalidate();
showAbove(true);
}
public void setMenu(int res) {
setMenu(LayoutInflater.from(getContext()).inflate(res, null));
}
public void setMenu(View v) {
mViewBehind.setMenu(v);
mViewBehind.invalidate();
}
public void setSlidingEnabled(boolean b) {
mViewAbove.setSlidingEnabled(b);
}
public boolean isSlidingEnabled() {
return mViewAbove.isSlidingEnabled();
}
/**
*
* #param b Whether or not the SlidingMenu is in a static mode
* (i.e. nothing is moving and everything is showing)
*/
public void setStatic(boolean b) {
if (b) {
setSlidingEnabled(false);
mViewAbove.setCustomViewBehind(null);
mViewAbove.setCurrentItem(1);
mViewBehind.setCurrentItem(0);
} else {
mViewAbove.setCurrentItem(1);
mViewBehind.setCurrentItem(1);
mViewAbove.setCustomViewBehind(mViewBehind);
setSlidingEnabled(true);
}
}
/**
* Shows the behind view
*/
public void showBehind(boolean b) {
mViewAbove.setCurrentItem(0, b);
}
public void showBehind() {
mViewAbove.setCurrentItem(0);
}
/**
* Shows the above view
*/
public void showAbove(boolean b) {
mViewAbove.setCurrentItem(1, b);
}
public void showAbove() {
mViewAbove.setCurrentItem(1);
}
/**
*
* #return Whether or not the behind view is showing
*/
public boolean isBehindShowing() {
return mViewAbove.getCurrentItem() == 0;
}
/**
*
* #return The margin on the right of the screen that the behind view scrolls to
*/
public int getBehindOffset() {
return ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams()).rightMargin;
}
/**
*
* #param i The margin on the right of the screen that the behind view scrolls to
*/
public void setBehindOffset(int i) {
RelativeLayout.LayoutParams params = ((RelativeLayout.LayoutParams)mViewBehind.getLayoutParams());
int bottom = params.bottomMargin;
int top = params.topMargin;
int left = params.leftMargin;
params.setMargins(left, top, i, bottom);
}
/**
*
* #param i The width the Sliding Menu will open to in pixels
*/
#SuppressWarnings("deprecation")
public void setBehindWidth(int i) {
int width;
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
try {
Class<?> cls = Display.class;
Class<?>[] parameterTypes = {Point.class};
Point parameter = new Point();
Method method = cls.getMethod("getSize", parameterTypes);
method.invoke(display, parameter);
width = parameter.x;
} catch (Exception e) {
width = display.getWidth();
}
setBehindOffset(width-i);
}
/**
*
* #param res A resource ID which points to the width the Sliding Menu will open to
*/
public void setBehindWidthRes(int res) {
int i = (int) getContext().getResources().getDimension(res);
setBehindWidth(i);
}
/**
*
* #param res The dimension resource to be set as the behind offset
*/
public void setBehindOffsetRes(int res) {
int i = (int) getContext().getResources().getDimension(res);
setBehindOffset(i);
}
/**
*
* #return The scale of the parallax scroll
*/
public float getBehindScrollScale() {
return mViewAbove.getScrollScale();
}
/**
*
* #param f The scale of the parallax scroll (i.e. 1.0f scrolls 1 pixel for every
* 1 pixel that the above view scrolls and 0.0f scrolls 0 pixels)
*/
public void setBehindScrollScale(float f) {
mViewAbove.setScrollScale(f);
}
public void setBehindCanvasTransformer(CanvasTransformer t) {
mViewBehind.setCanvasTransformer(t);
}
public int getTouchModeAbove() {
return mViewAbove.getTouchMode();
}
public void setTouchModeAbove(int i) {
if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) {
throw new IllegalStateException("TouchMode must be set to either" +
"TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN.");
}
mViewAbove.setTouchMode(i);
}
public int getTouchModeBehind() {
return mViewBehind.getTouchMode();
}
public void setTouchModeBehind(int i) {
if (i != TOUCHMODE_FULLSCREEN && i != TOUCHMODE_MARGIN) {
throw new IllegalStateException("TouchMode must be set to either" +
"TOUCHMODE_FULLSCREEN or TOUCHMODE_MARGIN.");
}
mViewBehind.setTouchMode(i);
}
public void setShadowDrawable(int resId) {
mViewAbove.setShadowDrawable(resId);
}
public void setShadowWidthRes(int resId) {
setShadowWidth((int)getResources().getDimension(resId));
}
public void setShadowWidth(int pixels) {
mViewAbove.setShadowWidth(pixels);
}
public void setFadeEnabled(boolean b) {
mViewAbove.setBehindFadeEnabled(b);
}
public void setFadeDegree(float f) {
mViewAbove.setBehindFadeDegree(f);
}
public void setSelectorEnabled(boolean b) {
mViewAbove.setSelectorEnabled(true);
}
public void setSelectedView(View v) {
mViewAbove.setSelectedView(v);
}
public void setSelectorDrawable(int res) {
mViewAbove.setSelectorDrawable(BitmapFactory.decodeResource(getResources(), res));
}
public void setSelectorDrawable(Bitmap b) {
mViewAbove.setSelectorDrawable(b);
}
public void setOnOpenListener(OnOpenListener listener) {
//mViewAbove.setOnOpenListener(listener);
mOpenListener = listener;
}
public void setOnCloseListener(OnCloseListener listener) {
//mViewAbove.setOnCloseListener(listener);
mCloseListener = listener;
}
public void setOnOpenedListener(OnOpenedListener listener) {
mViewAbove.setOnOpenedListener(listener);
}
public void setOnClosedListener(OnClosedListener listener) {
mViewAbove.setOnClosedListener(listener);
}
private static class SavedState extends BaseSavedState {
boolean mBehindShowing;
public SavedState(Parcelable superState) {
super(superState);
}
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBooleanArray(new boolean[]{mBehindShowing});
}
/*
public static final Parcelable.Creator<SavedState> CREATOR
= ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
});
SavedState(Parcel in) {
super(in);
boolean[] showing = new boolean[1];
in.readBooleanArray(showing);
mBehindShowing = showing[0];
}
*/
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.mBehindShowing = isBehindShowing();
return ss;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
if (ss.mBehindShowing) {
showBehind(true);
} else {
showAbove(true);
}
}
#Override
protected boolean fitSystemWindows(Rect insets) {
int leftPadding = getPaddingLeft() + insets.left;
int rightPadding = getPaddingRight() + insets.right;
int topPadding = insets.top;
int bottomPadding = insets.bottom;
this.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
return super.fitSystemWindows(insets);
}
}
What's wrong? How can I fix it? I'm using IntelliJ IDEA 12 CE. Thanks a lot for any help!
This can be resolved by recreating the R.java file.
1. Re-build OR
2. Change the 'android:id' in XML file to a new id and re-build. Make sure you manually change all references to this id.
Sometimes this does´t work even recreating the R.java file, cleaning and rebuilding the project.
for me it works until i delete \gen and \bin folders, then automatically were recreated with the new relationship between resources and their id´s.
I think the problem is just that the inflater cast your item to RelativeLayout and you can't cast a relativeLayout in your item (Maybe this post is more precise : ClassCastException). Perhaps you have to give up and retrieve your object using your id with findViewById.