Stop NestedScrollView from scrolling to top when custom view is redrawn - android

I have a custom view inside a NestedScrollView. Every time invalidate is called on the view, the layout scrolls to top of the custom view. I want the scroll position to be unchanged after the view has been redrawn. Any idea how this can be done?
I have tried implementing an onScrollChangeListener and onGlobalLayoutListener in combination to rescroll to the previously scrolled position, but it doesn't work. I have the following code in the onCreateView method of a fragment.
ViewTreeObserver observer = layoutView.getViewTreeObserver();
if (scrollListener != null) {
observer.removeOnScrollChangedListener(scrollListener);
} else {
scrollListener = new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
scrollX = layoutView.getScrollX();
scrollY = layoutView.getScrollY();
}
};
}
observer.addOnScrollChangedListener(scrollListener);
if (layoutListener != null) {
observer.removeOnGlobalLayoutListener(layoutListener);
} else {
layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (customView != null && scrollY != 0 && getUserVisibleHint()) {
layoutView.setVerticalScrollbarPosition(scrollY);
}
};
}
observer.addOnGlobalLayoutListener(layoutListener);
The following is the code for the onDraw and onMeasure method of the custom view.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (pieces == null) {
return;
}
int position = 0;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols && position < pieces.length; c++) {
Paint paint = (pieces[position] ? complete : empty);
int left = c * stepSize + borderSize + margin;
int right = left + stepSize - borderSize * 2;
int top = r * stepSize + borderSize;
int bottom = top + stepSize - borderSize * 2;
canvas.drawRect(left + borderSize, top + borderSize,
right + borderSize, bottom + borderSize, paint);
++position;
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
cols = width / stepSize;
rows = (int) Math.ceil((float) cells / (float) cols);
margin = (width - cols * stepSize) / 2;
int height = rows * stepSize;
setMeasuredDimension(width, Math.max(width, height));
}

Related

Android: Horizontal list new line break with trello like labels

I want to create a view in android that holds labels like Trello does.
The problem that I am facing is, how to create a new line break when the label holder reaches the max width capacity. I want to achieve something like this.
Also have to consider that the labels can have different width length.
I come to the idea of inflate a new horizontal view any time the sum of the width surpass the max capacity, but I don't know if exists other approach or more efficient way to solve this problem.
Thank you for the help.
With this case, I think you should use this and replace RecyclerView.
Just custom a ViewGroup by overriding onLayout and onMeasure method:
String[] dataList;
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
int curItemWidth, curItemHeight, curLeft, curTop, maxHeight;
//get the available size of child view
int viewLeft = this.getPaddingLeft();
int viewTop = this.getPaddingTop();
int viewRight = this.getMeasuredWidth() - this.getPaddingRight();
int viewBottom = this.getMeasuredHeight() - this.getPaddingBottom();
int viewWidth = viewRight - viewLeft;
int viewHeight = viewBottom - viewTop;
maxHeight = 0;
curLeft = viewLeft + getCurLeft(0, viewWidth, viewHeight, viewRight);
curTop = viewTop;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE)
continue;
//Get the maximum size of the child
child.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.AT_MOST));
curItemWidth = child.getMeasuredWidth();
curItemHeight = child.getMeasuredHeight();
//wrap is reach to the end
if (curLeft + curItemWidth >= viewRight) { //new row
curLeft = viewLeft + getCurLeft(i, viewWidth, viewHeight, viewRight);
curTop += maxHeight;
maxHeight = 0;
}
//do the layout
child.layout(curLeft, curTop, curLeft + curItemWidth, curTop + curItemHeight);
//store the max height
maxHeight = Math.max(maxHeight, curItemHeight);
curLeft += curItemWidth;
}
}
private int getCurLeft(int currentPosition, int viewWidth, int viewHeight, int viewRight) {
int childCount = getChildCount();
int currentMaxWidth = 0;
for (int i = currentPosition; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE)
continue;
child.measure(MeasureSpec.makeMeasureSpec(viewWidth, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.AT_MOST));
currentMaxWidth += child.getMeasuredWidth();
//wrap is reach to the end
if (currentMaxWidth >= viewRight) { //new row
return 0;
}
}
return (viewWidth - currentMaxWidth) / 2;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Measurement will ultimately be computing these values.
int childCount = getChildCount();
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
int currentRowWidth = 0;
int parentWidth = resolveSizeAndState(maxWidth, widthMeasureSpec, childState);
// Iterate through all children, measuring them and computing our dimensions
// from their size.
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE)
continue;
// Measure the child.
measureChild(child, widthMeasureSpec, heightMeasureSpec);
maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
currentRowWidth += child.getMeasuredWidth();
if (currentRowWidth >= parentWidth) { //create new row.
maxHeight += child.getMeasuredHeight();
currentRowWidth = 0;
}
childState = combineMeasuredStates(childState, child.getMeasuredState());
}
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Report our final dimensions.
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT));
}
public void setData(String[] dataList) {
this.dataList = dataList;
for (int i = 0; i < dataList.length; i++) {
View tagView = layoutInflater.inflate(R.layout.item_tag_layout, null, false);
TextView tagTextView = tagView.findViewById(R.id.label);
tagTextView.setText(dataList[i]);
tagTextView.setTag(i);
tagTextView.setOnClickListener(onClickListener);
if (dataList[i].equalsIgnoreCase(defaultItem)) {
selectedItemView = tagTextView;
tagTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.tag_layout_text_selected));
} else {
tagTextView.setTextColor(ContextCompat.getColor(getContext(), R.color.tag_layout_text_default));
}
if (i == dataList.length - 1) {
View indicator = tagView.findViewById(R.id.indicator);
indicator.setVisibility(GONE);
}
this.addView(tagView);
}
}

How to animate remove action in RelativeLayout?

I want to create custom container, that can lay children one by one from bottom with offset. Currently I created such container but I have problems with animation, when view is added to container it should slide from bottom, when view is remove it should slide to bottom. With add animation all fine, but with remove I got some issues, views dont want to go in needed position?
This is onLayout() method:
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int offset;
if (i > (itemCount - VISIBLE_ITEMS)) {
offset = (itemCount - i - 1) * this.offset;
}
// we adding invisible items
else {
offset = (VISIBLE_ITEMS - 1) * this.offset;
}
int bottom = getBottom() - offset;
int left = getLeft();
int right = getRight();
int top = bottom - child.getMeasuredHeight();
child.layout(left, top, right, bottom);
}
}
This is method for adding new view:
public void animateAdd(final View view){
addView(view);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
AnimatorSet animator = new AnimatorSet();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int startY = i == getChildCount() - 1 ? child.getHeight() : offset;
if (isNeedToAnimate(i)) {
Log.d(TAG, "onPreDraw: startY = " + startY);
animator.playTogether(ObjectAnimator.ofFloat(child, TRANSLATION_Y, startY, 0));
animator.playTogether(createColorAnimator(child, i));
}
}
animator.setDuration(300);
animator.start();
return true;
}
});
}
This is method for remove action:
public void animateRemove() {
if (getChildCount() == 0) {
return;
}
final View removeView = getChildAt(getChildCount() - 1);
removeViewInLayout(removeView);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
final AnimatorSet animator = new AnimatorSet();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int endY = i == getChildCount() - 1 ? child.getHeight() : offset;
if (isNeedToAnimateRemove(i)) {
Animator anim = ObjectAnimator.ofFloat(child, TRANSLATION_Y, endY);
animator.playTogether(anim);
animator.playTogether(createColorAnimator(child, i));
}
}
animator.setDuration(300);
animator.start();
return true;
}
});
}

how do i add activites in tabbar? please help me

this is my code which i follow from code.google.com this link http://code.google.com/p/android-playground/source/browse/#svn%2Ftrunk%2FSwipeyTabsSample
just tell me how do i add activites in this application? is show same activity in all tabs
public class SwipeyTabsSampleActivity extends FragmentActivity {
private static final String [] TITLES = {
"CATEGORIES",
"FEATURED",
"TOP PAID",
"TOP FREE",
"TOP GROSSING",
"TOP NEW PAID",
"TOP NEW FREE",
"TRENDING",
};
private SwipeyTabs mTabs;
private ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipeytab);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabs = (SwipeyTabs) findViewById(R.id.swipeytabs);
SwipeyTabsPagerAdapter adapter = new SwipeyTabsPagerAdapter(this,
getSupportFragmentManager());
mViewPager.setAdapter(adapter);
mTabs.setAdapter(adapter);
mViewPager.setOnPageChangeListener(mTabs);
mViewPager.setCurrentItem(0);
}
private class SwipeyTabsPagerAdapter extends FragmentPagerAdapter implements
SwipeyTabsAdapter {
private final Context mContext;
public SwipeyTabsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
#Override
public Fragment getItem(int position) {
return SwipeyTabFragment.newInstance(TITLES[position]);
}
#Override
public int getCount() {
return TITLES.length;
}
public TextView getTab(final int position, SwipeyTabs root) {
TextView view = (TextView) LayoutInflater.from(mContext).inflate(
R.layout.swipey_tab_indicator, root, false);
view.setText(TITLES[position]);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mViewPager.setCurrentItem(position);
}
});
return view;
}
}
}
public interface SwipeyTabsAdapter {
/**
* Return the number swipey tabs. Needs to be aligned with the number of
* items in your {#link PagerAdapter}.
*
* #return
*/
int getCount();
/**
* Build {#link TextView} to diplay as a swipey tab.
*
* #param position the position of the tab
* #param root the root view
* #return
*/
TextView getTab(int position, SwipeyTabs root);
}
public class SwipeyTabs extends ViewGroup implements
OnPageChangeListener {
protected final String TAG = "SwipeyTabs";
private SwipeyTabsAdapter mAdapter;
private int mCurrentPos = -1;
// height of the bar at the bottom of the tabs
private int mBottomBarHeight = 2;
// height of the indicator for the fronted tab
private int mTabIndicatorHeight = 3;
// color for the bottom bar, fronted tab
private int mBottomBarColor = 0xff96aa39;
// text color for all other tabs
private int mTextColor = 0xff949494;
// holds the positions of the fronted tabs
private int[] mFrontedTabPos;
// holds the positions of the target position when swiping left
private int[] mLeftTabPos;
// holds the positions of the target position when swiping right
private int[] mRightTabPos;
// holds the positions of the current position on screen
private int[] mCurrentTabPos;
private Paint mCachedTabPaint;
private int mWidth = -1;
public SwipeyTabs(Context context) {
this(context, null);
}
public SwipeyTabs(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SwipeyTabs(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SwipeyTabs, defStyle, 0);
mBottomBarColor = a.getColor(R.styleable.SwipeyTabs_bottomBarColor,
mBottomBarColor);
mBottomBarHeight = a.getDimensionPixelSize(
R.styleable.SwipeyTabs_bottomBarHeight, 2);
mTabIndicatorHeight = a.getDimensionPixelSize(
R.styleable.SwipeyTabs_tabIndicatorHeight, 3);
a.recycle();
init();
}
/**
* Initialize the SwipeyTabs {#link ViewGroup}
*/
private void init() {
// enable the horizontal fading edges which will be drawn by the parent
// View
setHorizontalFadingEdgeEnabled(true);
setFadingEdgeLength((int) (getResources().getDisplayMetrics().density *
35.0f + 0.5f));
setWillNotDraw(false);
mCachedTabPaint = new Paint();
mCachedTabPaint.setColor(mBottomBarColor);
}
/**
* Set the adapter.
*
* #param adapter
*/
public void setAdapter(SwipeyTabsAdapter adapter) {
if (mAdapter != null) {
// TODO: data set observer
}
mAdapter = adapter;
mCurrentPos = -1;
mFrontedTabPos = null;
mLeftTabPos = null;
mRightTabPos = null;
mCurrentTabPos = null;
// clean up our childs
removeAllViews();
if (mAdapter != null) {
final int count = mAdapter.getCount();
// add the child text views
for (int i = 0; i < count; i++) {
addView(mAdapter.getTab(i, this));
}
mCurrentPos = 0;
mFrontedTabPos = new int[count];
mLeftTabPos = new int[count];
mRightTabPos = new int[count];
mCurrentTabPos = new int[count];
mWidth = -1;
requestLayout();
}
}
/**
* Calculate the fronted, left and right positions
*
* #param forceLayout
* force the current positions to the values of the calculated
* fronted positions
*/
private void updateTabPositions(boolean forceLayout) {
if (mAdapter == null) {
return;
}
calculateTabPosition(mCurrentPos, mFrontedTabPos);
calculateTabPosition(mCurrentPos + 1, mLeftTabPos);
calculateTabPosition(mCurrentPos - 1, mRightTabPos);
updateEllipsize();
if (forceLayout) {
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
mCurrentTabPos[i] = mFrontedTabPos[i];
}
}
}
/**
* Calculate the position of the tabs.
*
* #param position
* the position of the fronted tab
* #param tabPositions
* the array in which to store the result
*/
private void calculateTabPosition(int position, int[] tabPositions) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
if (position >= 0 && position < count) {
final int width = getMeasuredWidth();
final View centerTab = getChildAt(position);
tabPositions[position] = width / 2 - centerTab.getMeasuredWidth()
/ 2;
for (int i = position - 1; i >= 0; i--) {
final TextView tab = (TextView) getChildAt(i);
if (i == position - 1) {
tabPositions[i] = 0 - tab.getPaddingLeft();
} else {
tabPositions[i] = 0 - tab.getMeasuredWidth() -
width;
}
tabPositions[i] = Math.min(tabPositions[i], tabPositions[i
+ 1]
- tab.getMeasuredWidth());
}
for (int i = position + 1; i < count; i++) {
final TextView tab = (TextView) getChildAt(i);
if (i == position + 1) {
tabPositions[i] = width - tab.getMeasuredWidth()
+ tab.getPaddingRight();
} else {
tabPositions[i] = width * 2;
}
final TextView prevTab = (TextView) getChildAt(i - 1);
tabPositions[i] = Math.max(tabPositions[i], tabPositions[i
- 1]
+ prevTab.getMeasuredWidth());
}
} else {
for (int i = 0; i < tabPositions.length; i++) {
tabPositions[i] = -1;
}
}
}
/**
* Update the ellipsize of the text views
*/
private void updateEllipsize() {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
TextView tab = (TextView) getChildAt(i);
if (i < mCurrentPos) {
tab.setEllipsize(null);
tab.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
} else if (i == mCurrentPos) {
tab.setEllipsize(TruncateAt.END);
tab.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
} else if (i > mCurrentPos) {
tab.setEllipsize(null);
tab.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
measureTabs(widthMeasureSpec, heightMeasureSpec);
int height = 0;
final View v = getChildAt(0);
if (v != null) {
height = v.getMeasuredHeight();
}
setMeasuredDimension(
resolveSize(getPaddingLeft() + widthSize +
getPaddingRight(),
widthMeasureSpec),
resolveSize(height + mBottomBarHeight + getPaddingTop()
+ getPaddingBottom(), heightMeasureSpec));
if (mWidth != widthSize) {
mWidth = widthSize;
updateTabPositions(true);
}
}
/**
* Measure our tab text views
*
* #param widthMeasureSpec
* #param heightMeasureSpec
*/
private void measureTabs(int widthMeasureSpec, int heightMeasureSpec) {
if (mAdapter == null) {
return;
}
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int maxWidth = (int) (widthSize * 0.6);
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
LayoutParams layoutParams = (LayoutParams) getChildAt(i)
.getLayoutParams();
final int widthSpec = MeasureSpec.makeMeasureSpec(maxWidth,
MeasureSpec.AT_MOST);
final int heightSpec = MeasureSpec.makeMeasureSpec(
layoutParams.height, MeasureSpec.EXACTLY);
getChildAt(i).measure(widthSpec, heightSpec);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
View v = getChildAt(i);
v.layout(mCurrentTabPos[i], this.getPaddingTop(), mCurrentTabPos[i]
+ v.getMeasuredWidth(),
this.getPaddingTop() + v.getMeasuredHeight());
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (mCurrentPos != -1) {
// calculate the relative position of the fronted tab to set the
// alpha channel of the tab indicator
final int tabSelectedTop = getHeight() - getPaddingBottom()
- mBottomBarHeight - mTabIndicatorHeight;
final View currentTab = getChildAt(mCurrentPos);
final int centerOfTab = (mCurrentTabPos[mCurrentPos] + currentTab
.getMeasuredWidth()) -
(currentTab.getMeasuredWidth() / 2);
final int center = getWidth() / 2;
final int centerDiv3 = center / 3;
final float relativePos = 1.0f - Math.min(
Math.abs((float) (centerOfTab - center)
/ (float) (centerDiv3)), 1.0f);
mCachedTabPaint.setAlpha((int) (255 * relativePos));
canvas.drawRect(
mCurrentTabPos[mCurrentPos],
tabSelectedTop,
mCurrentTabPos[mCurrentPos] +
currentTab.getMeasuredWidth(),
tabSelectedTop + mTabIndicatorHeight,
mCachedTabPaint);
// set the correct text colors on the text views
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
final TextView tab = (TextView) getChildAt(i);
if (mCurrentPos == i) {
tab.setTextColor(interpolateColor(mBottomBarColor,
mTextColor, 1.0f - relativePos));
} else {
tab.setTextColor(mTextColor);
}
}
}
super.dispatchDraw(canvas);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
// draw the bottom bar
final int bottomBarTop = getHeight() - getPaddingBottom()
- mBottomBarHeight;
mCachedTabPaint.setAlpha(0xff);
canvas.drawRect(0, bottomBarTop, getWidth(), bottomBarTop
+ mBottomBarHeight, mCachedTabPaint);
}
#Override
protected float getLeftFadingEdgeStrength() {
// forced so that we will always have the left fading edge
return 1.0f;
}
#Override
protected float getRightFadingEdgeStrength() {
// forced so that we will always have the right fading edge
return 1.0f;
}
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (mAdapter == null) {
return;
}
final int count = mAdapter.getCount();
float x = 0.0f;
int dir = 0;
// detect the swipe direction
if (positionOffsetPixels != 0 && mCurrentPos == position) {
dir = -1;
x = positionOffset;
} else if (positionOffsetPixels != 0 && mCurrentPos != position) {
dir = 1;
x = 1.0f - positionOffset;
}
// update the current positions
for (int i = 0; i < count; i++) {
final float curX = mFrontedTabPos[i];
float toX = 0.0f;
if (dir < 0) {
toX = mLeftTabPos[i];
} else if (dir > 0) {
toX = mRightTabPos[i];
} else {
toX = mFrontedTabPos[i];
}
final int offsetX = (int) ((toX - curX) * x + 0.5f);
final int newX = (int) (curX + offsetX);
mCurrentTabPos[i] = newX;
}
requestLayout();
invalidate();
}
public void onPageSelected(int position) {
mCurrentPos = position;
updateTabPositions(false);
}
private int interpolateColor(final int color1, final int color2,
float fraction) {
final float alpha1 = Color.alpha(color1) / 255.0f;
final float red1 = Color.red(color1) / 255.0f;
final float green1 = Color.green(color1) / 255.0f;
final float blue1 = Color.blue(color1) / 255.0f;
final float alpha2 = Color.alpha(color2) / 255.0f;
final float red2 = Color.red(color2) / 255.0f;
final float green2 = Color.green(color2) / 255.0f;
final float blue2 = Color.blue(color2) / 255.0f;
final float deltaAlpha = alpha2 - alpha1;
final float deltaRed = red2 - red1;
final float deltaGreen = green2 - green1;
final float deltaBlue = blue2 - blue1;
float alpha = alpha1 + (deltaAlpha * fraction);
float red = red1 + (deltaRed * fraction);
float green = green1 + (deltaGreen * fraction);
float blue = blue1 + (deltaBlue * fraction);
alpha = Math.max(Math.min(alpha, 1f), 0f);
red = Math.max(Math.min(red, 1f), 0f);
green = Math.max(Math.min(green, 1f), 0f);
blue = Math.max(Math.min(blue, 1f), 0f);
return Color.argb((int) (alpha * 255.0f), (int) (red * 255.0f),
(int) (green * 255.0f), (int) (blue * 255.0f));
}
}
public class SwipeyTabFragment extends Fragment {
public static Fragment newInstance(String title) {
SwipeyTabFragment f = new SwipeyTabFragment();
Bundle args = new Bundle();
args.putString("title", title);
f.setArguments(args);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_swipeytab,
null);
final String title = getArguments().getString("title");
((TextView) root.findViewById(R.id.text)).setText(title);
return root;
}
}
just tell me how do i add activites in this application? is show same activity in all tabs
You don't. Having activities-in-tabs was deprecated well over two years ago.
A ViewPager typically uses fragments for its pages, as is demonstrated in the code you pasted above. In this sample, each page is a SwipeyTabFragment, but you are welcome to have pages be different fragment classes if you prefer. You are also welcome to not use fragments and use custom Views instead for the pages. But there is no support for putting activities as pages.

android OnGlobalLayoutListener how to retrieve data

I am using OnGlobalLayoutListener. How can I use data from this listener? Especially I need lAngle.
past_edittext.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = past_edittext.getHeight();
int width = past_edittext.getWidth();
int top = past_edittext.getTop();
int left = past_edittext.getLeft();
// center coordinates of EditText
past_edittextX = left + width / 2;
past_edittextY = top + height / 2;
lAngle = (float) (Math
.atan((totalCenterY - past_edittextY)
/ (totalCenterX - past_edittextX)) * 180 / Math.PI);
}
});
in your class declare the following
private float lAngle;
then you can access lAngle after you've set it from the globallayoutlistener
...
past_edittext.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = past_edittext.getHeight();
int width = past_edittext.getWidth();
int top = past_edittext.getTop();
int left = past_edittext.getLeft();
// center coordinates of EditText
past_edittextX = left + width / 2;
past_edittextY = top + height / 2;
lAngle = (float) (Math
.atan((totalCenterY - past_edittextY)
/ (totalCenterX - past_edittextX)) * 180 / Math.PI);
}
});
}
public void someOtherMethod(){
if (lAngle != null)
// do something...

Help with Android UI ListView problems

To understand this question, first read how this method works.
I am trying to implements a drag and drop ListView, it's going alright but have run into
a road block. So I don't have to handled everything, I am intercepting(but returning false) MotionEvents sent to the ListView, letting it handle scrolling and stuff. When I want to start dragging a item, I then return true and handled all the dragging stuff. Everything is working fine except for one thing. The drag(drag and drop) is started when it is determined that a long press as a occurred(in onInterceptTouchEvent). I get the Bitmap for the image that I drag around like so. itemPositition being the index of the item that was selected.
(omitting irrelevant parts)
...
View dragItem = mListView.getChildAt(itemPosition);
dragItem.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(dragItem.getDrawingCache());
mDragImage = new ImageView(mContext);
mDragImage.setImageBitmap(bitmap);
...
The problem is, mDragImage is a solid black like this.
But, if I don't let ListView handle anything. As in, I start the drag on ACTION_DOWN and stop on ACTION_UP, mDragImage looks has expected(but I obviously lose scrolling abilities).
Since the drag is started with a long press, the ListView is given the opportunity to do things before the long press occurs. This is my guess as to why this is happening. When a item is pressed, it is highlighted by the ListView. Somewhere in doing so, it is messing with the bitmap. So when I go to get it, it's in a weird state(all black).
I see two options for fixing this, neither of which I know how to do.
Create a image from scratch.
Handle the highlighting myself(if that is the problem).
Option two seems a better one to me, except that I looked at the documentation and the source code and could not find out how to do so. Here are some things I have done/tried.
I set setOnItemClickListener(...) and
setOnItemSelectedListener(...) with a empty method(highlighting
still happens). (Before anyone suggests it, calling
setOnClickListener results in a runtime error.)
I also looked into trying to get the ListView to make a new item
(for option 2), but could not find a way.
Spent 45ish minutes looking through the source code and
documentation trying to pinpoint where the highlighting was
happening(I never found it).
Any help fixing this would be appreciated.
(EDIT1 START)
So I don't actually know if onLongClickListener is working, I made an error before thinking it was. I am trying to set it up right now, will update when I find out if it does.
(EDIT1 END)
Last minute edit before post. I tried using onLongClickListener just now, and the image is good. I would still like to know if there is another way. How I have to use onLongClickListener to get things working is ugly, but it works. I also spent so much time trying to figure this out, it would be nice to find out the answer. I still want to be able to change/handle the highlight color, the default orangeish color is not pretty. Oh and sorry about the length of the post. I could not think of way of making it shorter, while supplying all the information I thought was needed.
use this code, it's allows operation drug and drop in ListView:
public class DraggableListView extends ListView {
private static final String LOG_TAG = "tasks365";
private static final int END_OF_LIST_POSITION = -2;
private DropListener mDropListener;
private int draggingItemHoverPosition;
private int dragStartPosition; // where was the dragged item originally
private int mUpperBound; // scroll the view when dragging point is moving out of this bound
private int mLowerBound; // scroll the view when dragging point is moving out of this bound
private int touchSlop;
private Dragging dragging;
private GestureDetector longPressDetector;
public DraggableListView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.listViewStyle);
}
public DraggableListView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
longPressDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() {
#Override
public void onLongPress(final MotionEvent e) {
int x = (int) e.getX();
final int y = (int) e.getY();
int itemnum = pointToPosition(x, y);
if (itemnum == AdapterView.INVALID_POSITION) {
return;
}
if (dragging != null) {
dragging.stop();
dragging = null;
}
final View item = getChildAt(itemnum - getFirstVisiblePosition());
item.setPressed(false);
dragging = new Dragging(getContext());
dragging.start(y, ((int) e.getRawY()) - y, item);
draggingItemHoverPosition = itemnum;
dragStartPosition = draggingItemHoverPosition;
int height = getHeight();
mUpperBound = Math.min(y - touchSlop, height / 3);
mLowerBound = Math.max(y + touchSlop, height * 2 / 3);
}
});
setOnItemLongClickListener(new OnItemLongClickListener() {
#SuppressWarnings("unused")
public boolean onItemLongClick(AdapterView<?> paramAdapterView, View paramView, int paramInt, long paramLong) {
// Return true to let AbsListView reset touch mode
// Without this handler, the pressed item will keep highlight.
return true;
}
});
}
/* pointToPosition() doesn't consider invisible views, but we need to, so implement a slightly different version. */
private int myPointToPosition(int x, int y) {
if (y < 0) {
return getFirstVisiblePosition();
}
Rect frame = new Rect();
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
child.getHitRect(frame);
if (frame.contains(x, y)) {
return getFirstVisiblePosition() + i;
}
}
if ((x >= frame.left) && (x < frame.right) && (y >= frame.bottom)) {
return END_OF_LIST_POSITION;
}
return INVALID_POSITION;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (longPressDetector.onTouchEvent(ev)) {
return true;
}
if ((dragging == null) || (mDropListener == null)) {
// it is not dragging, or there is no drop listener
return super.onTouchEvent(ev);
}
int action = ev.getAction();
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
dragging.stop();
dragging = null;
if (mDropListener != null) {
if (draggingItemHoverPosition == END_OF_LIST_POSITION) {
mDropListener.drop(dragStartPosition, getCount() - 1);
} else if (draggingItemHoverPosition != INVALID_POSITION) {
mDropListener.drop(dragStartPosition, draggingItemHoverPosition);
}
}
resetViews();
break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
int x = (int) ev.getX();
int y = (int) ev.getY();
dragging.drag(x, y);
int position = dragging.calculateHoverPosition();
if (position != INVALID_POSITION) {
if ((action == MotionEvent.ACTION_DOWN) || (position != draggingItemHoverPosition)) {
draggingItemHoverPosition = position;
doExpansion();
}
scrollList(y);
}
break;
}
return true;
}
private void doExpansion() {
int expanItemViewIndex = draggingItemHoverPosition - getFirstVisiblePosition();
if (draggingItemHoverPosition >= dragStartPosition) {
expanItemViewIndex++;
}
// Log.v(LOG_TAG, "Dragging item hovers over position " + draggingItemHoverPosition + ", expand item at index "
// + expanItemViewIndex);
View draggingItemOriginalView = getChildAt(dragStartPosition - getFirstVisiblePosition());
for (int i = 0;; i++) {
View itemView = getChildAt(i);
if (itemView == null) {
break;
}
ViewGroup.LayoutParams params = itemView.getLayoutParams();
int height = LayoutParams.WRAP_CONTENT;
if (itemView.equals(draggingItemOriginalView)) {
height = 1;
} else if (i == expanItemViewIndex) {
height = itemView.getHeight() + dragging.getDraggingItemHeight();
}
params.height = height;
itemView.setLayoutParams(params);
}
}
/**
* Reset view to original height.
*/
private void resetViews() {
for (int i = 0;; i++) {
View v = getChildAt(i);
if (v == null) {
layoutChildren(); // force children to be recreated where needed
v = getChildAt(i);
if (v == null) {
break;
}
}
ViewGroup.LayoutParams params = v.getLayoutParams();
params.height = LayoutParams.WRAP_CONTENT;
v.setLayoutParams(params);
}
}
private void resetScrollBounds(int y) {
int height = getHeight();
if (y >= height / 3) {
mUpperBound = height / 3;
}
if (y <= height * 2 / 3) {
mLowerBound = height * 2 / 3;
}
}
private void scrollList(int y) {
resetScrollBounds(y);
int height = getHeight();
int speed = 0;
if (y > mLowerBound) {
// scroll the list up a bit
speed = y > (height + mLowerBound) / 2 ? 16 : 4;
} else if (y < mUpperBound) {
// scroll the list down a bit
speed = y < mUpperBound / 2 ? -16 : -4;
}
if (speed != 0) {
int ref = pointToPosition(0, height / 2);
if (ref == AdapterView.INVALID_POSITION) {
//we hit a divider or an invisible view, check somewhere else
ref = pointToPosition(0, height / 2 + getDividerHeight() + 64);
}
View v = getChildAt(ref - getFirstVisiblePosition());
if (v != null) {
int pos = v.getTop();
setSelectionFromTop(ref, pos - speed);
}
}
}
public void setDropListener(DropListener l) {
mDropListener = l;
}
public interface DropListener {
void drop(int from, int to);
}
class Dragging {
private Context context;
private WindowManager windowManager;
private WindowManager.LayoutParams mWindowParams;
private ImageView mDragView;
private Bitmap mDragBitmap;
private int coordOffset;
private int mDragPoint; // at what offset inside the item did the user grab it
private int draggingItemHeight;
private int x;
private int y;
private int lastY;
public Dragging(Context context) {
this.context = context;
windowManager = (WindowManager) context.getSystemService("window");
}
/**
* #param y
* #param offset - the difference in y axis between screen coordinates and coordinates in this view
* #param view - which view is dragged
*/
public void start(int y, int offset, View view) {
this.y = y;
lastY = y;
this.coordOffset = offset;
mDragPoint = y - view.getTop();
draggingItemHeight = view.getHeight();
mDragView = new ImageView(context);
mDragView.setBackgroundResource(android.R.drawable.alert_light_frame);
// Create a copy of the drawing cache so that it does not get recycled
// by the framework when the list tries to clean up memory
view.setDrawingCacheEnabled(true);
mDragBitmap = Bitmap.createBitmap(view.getDrawingCache());
mDragView.setImageBitmap(mDragBitmap);
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP;
mWindowParams.x = 0;
mWindowParams.y = y - mDragPoint + coordOffset;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.windowAnimations = 0;
windowManager.addView(mDragView, mWindowParams);
}
public void drag(int x, int y) {
lastY = this.y;
this.x = x;
this.y = y;
mWindowParams.y = y - mDragPoint + coordOffset;
windowManager.updateViewLayout(mDragView, mWindowParams);
}
public void stop() {
if (mDragView != null) {
windowManager.removeView(mDragView);
mDragView.setImageDrawable(null);
mDragView = null;
}
if (mDragBitmap != null) {
mDragBitmap.recycle();
mDragBitmap = null;
}
}
public int getDraggingItemHeight() {
return draggingItemHeight;
}
public int calculateHoverPosition() {
int adjustedY = (int) (y - mDragPoint + (Math.signum(y - lastY) + 2) * draggingItemHeight / 2);
// Log.v(LOG_TAG, "calculateHoverPosition(): lastY=" + lastY + ", y=" + y + ", adjustedY=" + adjustedY);
int pos = myPointToPosition(0, adjustedY);
if (pos >= 0) {
if (pos >= dragStartPosition) {
pos -= 1;
}
}
return pos;
}
}
}

Categories

Resources