I am using one custom designed CalendarView in Android. While I am using Scrollview in the layout, the custom designed CalendarView is not getting displayed in the screen.
what could cause the CalendarView to disappear?
My layout is:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/NextMonth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="#string/NextMonth" />
<Button
android:id="#+id/PreviousMonth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="#string/PreviousMonth" />
<TextView
android:id="#+id/MonthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Month" />
<TextView
android:id="#+id/SundayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="25dp"
android:text="#string/SundayText"
android:textSize="10sp" />
<TextView
android:id="#+id/MondayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="22dp"
android:layout_toRightOf="#+id/SundayText"
android:text="#string/MondayText"
android:textSize="10sp" />
<TextView
android:id="#+id/TuesdayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#+id/MondayText"
android:text="#string/Tuesday"
android:textSize="10sp" />
<TextView
android:id="#+id/WednesdayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="22dp"
android:layout_toRightOf="#+id/TuesdayText"
android:text="#string/Wednesday"
android:textSize="10sp" />
<TextView
android:id="#+id/Thursday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="20dp"
android:layout_toRightOf="#+id/WednesdayText"
android:text="#string/ThurdayText"
android:textSize="10sp" />
<TextView
android:id="#+id/Friday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="22dp"
android:layout_toRightOf="#+id/Thursday"
android:text="#string/FridayText"
android:textSize="10sp" />
<TextView
android:id="#+id/Saturday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/PreviousMonth"
android:layout_marginLeft="27dp"
android:layout_toRightOf="#+id/Friday"
android:text="#string/SaturdayText"
android:textSize="10sp" />
<com.example.calendar_module.CalendarView
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/NextMonth" />
</RelativeLayout>
</ScrollView>
My CalenderView Class file :
package com.example.calendar_module;
import java.util.Calendar;
import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.MonthDisplayHelper;
import android.view.MotionEvent;
import android.widget.ImageView;
public class CalendarView extends ImageView {
private static int WEEK_TOP_MARGIN = 0;
private static int WEEK_LEFT_MARGIN = 05;
private static int CELL_WIDTH = 20;
private static int CELL_HEIGH = 20;
private static int CELL_MARGIN_TOP = 05;
private static int CELL_MARGIN_LEFT = 29;
private static float CELL_TEXT_SIZE;
private static final String TAG = "CalendarView";
private String[] mDayString = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
private Calendar mRightNow = null;
private Drawable mWeekTitle = null;
private Cell mToday = null;
private Cell[][] mCells = new Cell[6][7];
private Cell[] mDayCells = new Cell[7];
private OnCellTouchListener mOnCellTouchListener = null;
MonthDisplayHelper mHelper;
Drawable mDecoration = null;
public interface OnCellTouchListener {
public void onTouch(Cell cell);
}
public CalendarView(Context context) {
this(context, null);
}
public CalendarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CalendarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDecoration = context.getResources().getDrawable(R.drawable.typeb_calendar_today);
initCalendarView();
}
private void initCalendarView() {
mRightNow = Calendar.getInstance();
// prepare static vars
Resources res = getResources();
WEEK_TOP_MARGIN = (int) res.getDimension(R.dimen.week_top_margin);
WEEK_LEFT_MARGIN = (int) res.getDimension(R.dimen.week_left_margin);
CELL_WIDTH = (int) res.getDimension(R.dimen.cell_width);
CELL_HEIGH = (int) res.getDimension(R.dimen.cell_heigh);
CELL_MARGIN_TOP = (int) res.getDimension(R.dimen.cell_margin_top);
CELL_MARGIN_LEFT = (int) res.getDimension(R.dimen.cell_margin_left);
CELL_TEXT_SIZE = res.getDimension(R.dimen.cell_text_size);
// set background
// setImageResource(R.drawable.background);
mWeekTitle = res.getDrawable(R.drawable.calendar_week);
mHelper = new MonthDisplayHelper(mRightNow.get(Calendar.YEAR), mRightNow.get(Calendar.MONTH));
}
private void initCells() {
class _calendar {
public int day;
public boolean thisMonth;
public _calendar(int d, boolean b) {
day = d;
thisMonth = b;
}
public _calendar(int d) {
this(d, false);
}
};
_calendar tmp[][] = new _calendar[6][7];
for(int i=0; i<tmp.length; i++) {
int n[] = mHelper.getDigitsForRow(i);
for(int d=0; d<n.length; d++) {
if(mHelper.isWithinCurrentMonth(i,d))
tmp[i][d] = new _calendar(n[d], true);
else
tmp[i][d] = new _calendar(n[d]);
}
}
Calendar today = Calendar.getInstance();
int thisDay = 0;
mToday = null;
if(mHelper.getYear()==today.get(Calendar.YEAR) && mHelper.getMonth()==today.get(Calendar.MONTH)) {
thisDay = today.get(Calendar.DAY_OF_MONTH);
}
// // build cells
Rect Bound = new Rect(CELL_MARGIN_LEFT, CELL_MARGIN_TOP, CELL_WIDTH+CELL_MARGIN_LEFT, CELL_HEIGH+CELL_MARGIN_TOP);
// for( int i=0 ; i < 7 ; i++ )
// {
//
// mDayCells[i] = new Cell(mDayString[i],new Rect(Bound),CELL_TEXT_SIZE);
// Bound.offset(CELL_WIDTH, 0);
//
// }
//
// Bound.offset(0, CELL_HEIGH); // move to next row and first column
// Bound.left = CELL_MARGIN_LEFT;
// Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;
//
for(int week=0; week<mCells.length; week++) {
for(int day=0; day<mCells[week].length; day++)
{
if(tmp[week][day].thisMonth) {
if(day==0 || day==6 )
mCells[week][day] = new RedCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
else
mCells[week][day] = new Cell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
} else {
mCells[week][day] = new GrayCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE);
}
Bound.offset(CELL_WIDTH, 0); // move to next column
// get today
if(tmp[week][day].day==thisDay && tmp[week][day].thisMonth) {
mToday = mCells[week][day];
mDecoration.setBounds(mToday.getBound());
}
}
Bound.offset(0, CELL_HEIGH); // move to next row and first column
Bound.left = CELL_MARGIN_LEFT;
Bound.right = CELL_MARGIN_LEFT+CELL_WIDTH;
}
}
#Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
// Rect re = getDrawable().getBounds();
// WEEK_LEFT_MARGIN = CELL_MARGIN_LEFT = (right-left - re.width()) / 2;
// mWeekTitle.setBounds(WEEK_LEFT_MARGIN, WEEK_TOP_MARGIN, WEEK_LEFT_MARGIN+mWeekTitle.getMinimumWidth(), WEEK_TOP_MARGIN+mWeekTitle.getMinimumHeight());
initCells();
super.onLayout(changed, left, top, right, bottom);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(CELL_WIDTH, CELL_HEIGH);
}
public void setTimeInMillis(long milliseconds) {
mRightNow.setTimeInMillis(milliseconds);
initCells();
this.invalidate();
}
public int getYear() {
return mHelper.getYear();
}
public int getMonth() {
return mHelper.getMonth();
}
public void nextMonth() {
mHelper.nextMonth();
initCells();
invalidate();
}
public void previousMonth() {
mHelper.previousMonth();
initCells();
invalidate();
}
public boolean firstDay(int day) {
return day==1;
}
public boolean lastDay(int day) {
return mHelper.getNumberOfDaysInMonth()==day;
}
public void goToday() {
Calendar cal = Calendar.getInstance();
mHelper = new MonthDisplayHelper(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH));
initCells();
invalidate();
}
public Calendar getDate() {
return mRightNow;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mOnCellTouchListener!=null){
for(Cell[] week : mCells) {
for(Cell day : week) {
if(day.hitTest((int)event.getX(), (int)event.getY())) {
mOnCellTouchListener.onTouch(day);
}
}
}
}
return super.onTouchEvent(event);
}
public void setOnCellTouchListener(OnCellTouchListener p) {
mOnCellTouchListener = p;
}
#Override
protected void onDraw(Canvas canvas) {
// draw background
super.onDraw(canvas);
mWeekTitle.draw(canvas);
// draw cells
for(Cell[] week : mCells) {
for(Cell day : week) {
day.draw(canvas);
}
}
// draw today
if(mDecoration!=null && mToday!=null) {
mDecoration.draw(canvas);
}
}
public class GrayCell extends Cell {
public GrayCell(int dayOfMon, Rect rect, float s) {
super(dayOfMon, rect, s);
mPaint.setColor(Color.LTGRAY);
}
}
private class RedCell extends Cell {
public RedCell(int dayOfMon, Rect rect, float s) {
super(dayOfMon, rect, s);
mPaint.setColor(0xdddd0000);
}
}
}
I think, height of your custom view equals == 0. try to log it. If it is right just override onMeasure and set size for your view.
And esle : why in xml height == match_parent? Can you imagine how it looks in ScrollView?)
UPD: Ok, in your case height == 0. You must override onMeasure() method in your custom view like this :
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(WIDTH, HEIGHT);
}
Where width and height values in pixels.
Good luck!
Related
I have CustomView with 2 RelativeLayouts. There are RecyclerViews in each RelativeLayout. When I add new element to RecyclerView it doesn`t change height.
If I change screen orientation then android measures it well. So my question is how to programmatically tell android that he needs remeasure both childs and parent elements.
requestlayout() and invalidate() doesn`t work
CustomView:
public class ExpandableView extends LinearLayout {
private Settings mSettings ;
private int mExpandState;
private ValueAnimator mExpandAnimator;
private ValueAnimator mParentAnimator;
private AnimatorSet mExpandScrollAnimatorSet;
private int mExpandedViewHeight;
private boolean mIsInit = true;
private int defaultHeight;
private boolean isAllowedExpand = false;
private ScrolledParent mScrolledParent;
private OnExpandListener mOnExpandListener;
public ExpandableView(Context context) {
super(context);
init(null);
}
public ExpandableView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public ExpandableView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init(AttributeSet attrs) {
Log.w("tag", "init");
setOrientation(VERTICAL);
this.setClipChildren(false);
this.setClipToPadding(false);
mExpandState = ExpandState.PRE_INIT;
mSettings = new Settings();
if(attrs!=null) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ExpandableView);
mSettings.expandDuration = typedArray.getInt(R.styleable.ExpandableView_expDuration, Settings.EXPAND_DURATION);
mSettings.expandWithParentScroll = typedArray.getBoolean(R.styleable.ExpandableView_expWithParentScroll,false);
mSettings.expandScrollTogether = typedArray.getBoolean(R.styleable.ExpandableView_expExpandScrollTogether,true);
typedArray.recycle();
}
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.w("tag", "onMeasure");
Log.w("tag", "widthMeasureSpec - " + widthMeasureSpec);
Log.w("tag", "heightMeasureSpec - " + heightMeasureSpec);
int childCount = getChildCount();
if(childCount!=2) {
throw new IllegalStateException("ExpandableLayout must has two child view !");
}
if(mIsInit) {
((MarginLayoutParams)getChildAt(0).getLayoutParams()).bottomMargin=0;
MarginLayoutParams marginLayoutParams = ((MarginLayoutParams)getChildAt(1).getLayoutParams());
marginLayoutParams.bottomMargin=0;
marginLayoutParams.topMargin=0;
marginLayoutParams.height = 0;
mExpandedViewHeight = getChildAt(1).getMeasuredHeight();
defaultHeight = mExpandedViewHeight;
mIsInit =false;
mExpandState = ExpandState.CLOSED;
View view = getChildAt(0);
if (view != null){
view.setOnClickListener(v -> toggle());
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.w("tag", "onSizeChanged");
if(mSettings.expandWithParentScroll) {
mScrolledParent = Utils.getScrolledParent(this);
}
}
private int getParentScrollDistance () {
int distance = 0;
Log.w("tag", "getParentScrollDistance");
if(mScrolledParent == null) {
return distance;
}
distance = (int) (getY() + getMeasuredHeight() + mExpandedViewHeight - mScrolledParent.scrolledView.getMeasuredHeight());
for(int index = 0; index < mScrolledParent.childBetweenParentCount; index++) {
ViewGroup parent = (ViewGroup) getParent();
distance+=parent.getY();
}
return distance;
}
private void verticalAnimate(final int startHeight, final int endHeight ) {
int distance = getParentScrollDistance();
final View target = getChildAt(1);
mExpandAnimator = ValueAnimator.ofInt(startHeight,endHeight);
mExpandAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
target.getLayoutParams().height = (int) animation.getAnimatedValue();
target.requestLayout();
}
});
mExpandAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if(endHeight-startHeight < 0) {
mExpandState = ExpandState.CLOSED;
if (mOnExpandListener != null) {
mOnExpandListener.onExpand(false);
}
} else {
mExpandState=ExpandState.EXPANDED;
if(mOnExpandListener != null) {
mOnExpandListener.onExpand(true);
}
}
}
});
mExpandState=mExpandState==ExpandState.EXPANDED?ExpandState.CLOSING :ExpandState.EXPANDING;
mExpandAnimator.setDuration(mSettings.expandDuration);
if(mExpandState == ExpandState.EXPANDING && mSettings.expandWithParentScroll && distance > 0) {
mParentAnimator = Utils.createParentAnimator(mScrolledParent.scrolledView, distance, mSettings.expandDuration);
mExpandScrollAnimatorSet = new AnimatorSet();
if(mSettings.expandScrollTogether) {
mExpandScrollAnimatorSet.playTogether(mExpandAnimator,mParentAnimator);
} else {
mExpandScrollAnimatorSet.playSequentially(mExpandAnimator,mParentAnimator);
}
mExpandScrollAnimatorSet.start();
} else {
mExpandAnimator.start();
}
}
public void setExpand(boolean expand) {
if (mExpandState == ExpandState.PRE_INIT) {return;}
getChildAt(1).getLayoutParams().height = expand ? mExpandedViewHeight : 0;
requestLayout();
mExpandState=expand?ExpandState.EXPANDED:ExpandState.CLOSED;
}
public boolean isExpanded() {
return mExpandState==ExpandState.EXPANDED;
}
public void toggle() {
if (isAllowedExpand){
if(mExpandState==ExpandState.EXPANDED) {
close();
}else if(mExpandState==ExpandState.CLOSED) {
expand();
}
}
}
public void expand() {
verticalAnimate(0,mExpandedViewHeight);
}
public void close() {
verticalAnimate(mExpandedViewHeight,0);
}
public interface OnExpandListener {
void onExpand(boolean expanded) ;
}
public void setOnExpandListener(OnExpandListener onExpandListener) {
this.mOnExpandListener = onExpandListener;
}
public void setExpandScrollTogether(boolean expandScrollTogether) {
this.mSettings.expandScrollTogether = expandScrollTogether;
}
public void setExpandWithParentScroll(boolean expandWithParentScroll) {
this.mSettings.expandWithParentScroll = expandWithParentScroll;
}
public void setExpandDuration(int expandDuration) {
this.mSettings.expandDuration = expandDuration;
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.w("tag", "onDetachedFromWindow");
if(mExpandAnimator!=null&&mExpandAnimator.isRunning()) {
mExpandAnimator.cancel();
mExpandAnimator.removeAllUpdateListeners();
}
if(mParentAnimator!=null&&mParentAnimator.isRunning()) {
mParentAnimator.cancel();
mParentAnimator.removeAllUpdateListeners();
}
if(mExpandScrollAnimatorSet!=null) {
mExpandScrollAnimatorSet.cancel();
}
}
public void setAllowedExpand(boolean allowedExpand) {
isAllowedExpand = allowedExpand;
}
public void increaseDistance(int size){
if(mExpandState==ExpandState.EXPANDED) {
close();
}
mExpandedViewHeight = defaultHeight + size;
}
//func just for loggs
public void showParams(){
RelativeLayout relativeLayout = (RelativeLayout) getChildAt(1);
/*relativeLayout.requestLayout();
relativeLayout.invalidate();*/
RecyclerView recyclerView = (RecyclerView) relativeLayout.getChildAt(1);
Log.d("tag", "height - " + relativeLayout.getHeight());
Log.d("tag", "childs - " + relativeLayout.getChildCount());
Log.d("tag", "recycler height - " + recyclerView.getHeight());
recyclerView.requestLayout();
recyclerView.invalidateItemDecorations();
recyclerView.invalidate();
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
layoutManager.getHeight();
Log.d("tag", " layoutManager.getHeight() - " + layoutManager.getHeight());
layoutManager.requestLayout();
layoutManager.generateDefaultLayoutParams();
layoutManager.onItemsChanged(recyclerView);
Log.d("tag", " layoutManager.getHeight()2- " + layoutManager.getHeight());
layoutManager.getChildCount();
recyclerView.getChildCount();
Log.d("tag", "manager childs - " + layoutManager.getChildCount());
Log.d("tag", "recycler childs - " + recyclerView.getChildCount());
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/grey_light_color"
>
<com.example.develop.project.Utils.ExpandableView.ExpandableView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/test_custom_view"
app:expWithParentScroll="true"
android:layout_gravity="center"
android:background="#color/grey_color"
>
<android.support.v7.widget.CardView
android:id="#+id/start_card"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="#color/white_color"
android:layout_marginTop="5dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/stage_tv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/grey_deep_color"
android:text="Запуск"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:textSize="18sp"
/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/start_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/start_accept"
android:textSize="18sp"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:textColor="#color/grey_deep_color"
android:layout_marginEnd="15dp"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_test_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/start_tv"
android:layout_marginTop="10dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
>
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
</com.example.develop.project.Utils.ExpandableView.ExpandableView>
<Button
android:id="#+id/add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:text="Add elem"
android:layout_marginStart="15dp"
android:layout_marginBottom="15dp"
/>
<Button
android:id="#+id/check_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:text="Check params"
android:layout_marginBottom="15dp"
android:layout_marginEnd="15dp"
/>
</RelativeLayout>
Activity:
public class TestActivity extends MvpAppCompatActivity implements TestContract.View {
TestAdapter testAdapter;
#InjectPresenter
public TestPresenter presenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
init();
}
private void init() {
ExpandableView expandableView = findViewById(R.id.test_custom_view);
expandableView.setAllowedExpand(true);
Button add_btn = findViewById(R.id.add_btn);
Button check_btn = findViewById(R.id.check_btn);
add_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
presenter.addElem();
}
});
check_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
expandableView.showParams();
}
});
}
#Override
public void addElems(ArrayList<String> list) {
testAdapter.notifyDataSetChanged();
}
#Override
public void populateAdapter(ArrayList<String> list) {
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
RecyclerView recyclerView = findViewById(R.id.my_test_tv);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
testAdapter = new TestAdapter(list);
recyclerView.setAdapter(testAdapter);
}
}
Adapter:
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.TasksViewHolder> {
private List<String> list;
public TestAdapter(List<String> list) {
this.list = list;
}
#NonNull
#Override
public TestAdapter.TasksViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.test_item, parent, false);
TestAdapter.TasksViewHolder vh = new TestAdapter.TasksViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(#NonNull TestAdapter.TasksViewHolder holder, int position) {
String text = list.get(position);
holder.textView.setText(text);
}
public static class TasksViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public TasksViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.my_test_tv);
}
}
#Override
public int getItemCount() {
return list.size();
}
}
The ExpandableView contains some suspicious code in its onMeasure method.
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
...
if(mIsInit) {
((MarginLayoutParams)getChildAt(0).getLayoutParams()).bottomMargin=0;
MarginLayoutParams marginLayoutParams = ((MarginLayoutParams)getChildAt(1).getLayoutParams());
marginLayoutParams.bottomMargin=0;
marginLayoutParams.topMargin=0;
marginLayoutParams.height = 0;
mExpandedViewHeight = getChildAt(1).getMeasuredHeight();
defaultHeight = mExpandedViewHeight;
mIsInit =false;
mExpandState = ExpandState.CLOSED;
View view = getChildAt(0);
if (view != null){
view.setOnClickListener(v -> toggle());
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
The mIsInit variable is set to true on creation and than to false when onMeasure is called for the first time. So the code in the condition runs only once.
But it stores value mExpandedViewHeight obtained as getChildAt(1).getMeasuredHeight() and that is current height of your relative layout, which contains (still empty) RecyclerView.
As far as I can see there's nothing in ExpadableView's code that would update this value, when you add an item to the Recylerview.
I am not sure, what would the correct/perfect implementation of the onMeasure method be (for your component). That would require some debugging and testing of the component, and perhaps some tweaks in other parts of the code.
If you wrote the component, you may want to invest more effort into debugging. If you didn't write the component, you should try to find other one, that is properly implemented. Custom components with custom measurements are an advanced topic.
If you really want to go with debugging and fixing your component, that first thing to do is to update the mExpandedViewHeight value on every measurement, but that might require updating other values that are derived from this value.
I'm creating a Scrolling Activity in my Android App. The Activity has a CollapsingToolbarLayout with parallax effect.
When I scroll the layout below the appbarlayout up, it'll go up smoothly and the appbarlayout will be collapsed up to the title.The ImageView and the TextView will go up to the title. And when I scroll the layout back down, they'll all go back down to the beginning.
The bug is here:
when I running the activity on some devices, sometimes when I scroll it up, the layout will be stucked there up and down for seconds and then, back go to the top.
And when I running the activity on some other devices, it'll be OK, nothing wrong happened.
The demo of this bug: https://share.weiyun.com/1d797a4a92580e1595eacb226f9a92a3
Here is the layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="nczz.cn.helloworld.ScrollingActivity"
>
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:background="#FA7199"
app:layout_scrollFlags="scroll|enterAlways"
android:theme="#style/AppTheme.AppBarOverlay">
<nczz.cn.widget.CollapsingImageTextLayout
android:id="#+id/imageTextLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title_id="#+id/test_title"
app:text_id="#+id/test_text"
app:img_scale="0.6"
app:text_scale="0.6"
app:text_margin_left="110dp"
app:img_id="#+id/test_img"
app:img_margin_left="55dp"
>
<LinearLayout
android:id="#+id/test_title"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#FA7199"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<ImageView
android:id="#+id/return_btn"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginLeft="20dp"
android:layout_centerVertical="true"
android:src="#drawable/left" />
</LinearLayout>
<ImageView
android:id="#+id/test_img"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="fitXY"
android:src="#mipmap/ic_launcher"
android:layout_centerInParent="true"
android:layout_marginBottom="30dp"
/>
<TextView
android:id="#+id/test_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/test_img"
android:text="MoveText"
android:textSize="20sp"
android:textColor="#android:color/white"
android:layout_marginTop="-20dp"
android:layout_marginLeft="50dp"
android:layout_centerInParent="true"
/>
</nczz.cn.widget.CollapsingImageTextLayout>
</android.support.design.widget.AppBarLayout>
<include
android:id="#+id/includelayout"
layout="#layout/content_scrolling"/>
</android.support.design.widget.CoordinatorLayout>
Here is the CollapsingImageTextLayout:
package nczz.cn.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;
import nczz.cn.helloworld.R;
/**
* Created by yahui.hu on 2017/4/21.
*/
public class CollapsingImageTextLayout extends RelativeLayout {
private AppBarLayout.OnOffsetChangedListener mOffsetChangedListener;
private int mTitleId, mTextId, mImageId;
private int mTitleMarginLeft, mTitleMarginTop, mImgMarginLeft, mImgMarginTop;
private float mTextScale, mImgScale;
private View mTitle, mImg, mText;
private boolean isGetView = true;
private int mTitleHeight = 0;
public CollapsingImageTextLayout(Context context) {
this(context, null);
}
public CollapsingImageTextLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CollapsingImageTextLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CollapsingImageLayout, defStyleAttr, 0);
mTitleId = a.getResourceId(R.styleable.CollapsingImageLayout_title_id, 0);
mTextId = a.getResourceId(R.styleable.CollapsingImageLayout_text_id, 0);
mImageId = a.getResourceId(R.styleable.CollapsingImageLayout_img_id, 0);
mTextScale = a.getFloat(R.styleable.CollapsingImageLayout_text_scale, 0.4f);
mImgScale = a.getFloat(R.styleable.CollapsingImageLayout_img_scale, 0.4f);
mTitleMarginLeft = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_text_margin_left, 0);
mTitleMarginTop = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_text_margin_top, 0);
mImgMarginLeft = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_img_margin_left, 0);
mImgMarginTop = a.getDimensionPixelSize(R.styleable.CollapsingImageLayout_img_margin_top, 0);
a.recycle();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
getView();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void getView() {
if (!isGetView) {
return;
}
if (mTitleId != 0) {
mTitle = findViewById(mTitleId);
}
if (mTextId != 0) {
mText = findViewById(mTextId);
}
if (mImageId != 0) {
mImg = findViewById(mImageId);
}
isGetView = false;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mTitle != null) {
getViewOffsetHelper(mTitle).onViewLayout(0, 0);
setMinimumHeight(getHeightWithMargins(mTitle));
mTitleHeight = mTitle.getHeight();
this.bringChildToFront(mTitle);
}
if (mImg != null) {
getViewOffsetHelper(mImg).onViewLayout(mImgMarginLeft, mImgMarginTop);
this.bringChildToFront(mImg);
}
if (mText != null) {
getViewOffsetHelper(mText).onViewLayout(mTitleMarginLeft, mTitleMarginTop);
this.bringChildToFront(mText);
}
}
static ViewHelper getViewOffsetHelper(View view) {
ViewHelper offsetHelper = (ViewHelper) view.getTag(R.id.view_helper);
if (offsetHelper == null) {
offsetHelper = new ViewHelper(view);
view.setTag(R.id.view_helper, offsetHelper);
}
return offsetHelper;
}
private static int getHeightWithMargins(#NonNull final View view) {
final ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp instanceof MarginLayoutParams) {
final MarginLayoutParams mlp = (MarginLayoutParams) lp;
return view.getHeight() + mlp.topMargin + mlp.bottomMargin;
}
return view.getHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent viewParent = getParent();
if (viewParent instanceof AppBarLayout) {
if (mOffsetChangedListener == null) mOffsetChangedListener = new OffsetListenerImp();
((AppBarLayout) viewParent).addOnOffsetChangedListener(mOffsetChangedListener);
}
}
#Override
protected void onDetachedFromWindow() {
ViewParent viewParent = getParent();
if (viewParent instanceof AppBarLayout) {
((AppBarLayout) viewParent).removeOnOffsetChangedListener(mOffsetChangedListener);
}
super.onDetachedFromWindow();
}
final int getMaxOffsetForPinChild(View child) {
final ViewHelper offsetHelper = getViewOffsetHelper(child);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
return getHeight()
- offsetHelper.getLayoutTop()
- child.getHeight()
- lp.bottomMargin;
}
static int constrain(int amount, int low, int high) {
return amount < low ? low : (amount > high ? high : amount);
}
static int constrain(int amount, int low) {
return amount < low ? low : amount;
}
private void setTopAndBottomOffset(View child, int verticalOffset) {
ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper);
viewHelper.setTopAndBottomOffset(
constrain(-verticalOffset, 0, getMaxOffsetForPinChild(child)));
Log.e("setTopAndBottomOffset",""+-verticalOffset);
}
private void setTopAndBottomOffset(View child, int verticalOffset, float scale) {
ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper);
viewHelper.setTopAndBottomOffset(
constrain(-verticalOffset - getMaxOffset(viewHelper, scale),
0));
//Log.e("setTopAndBottomOffset",""+-verticalOffset);
}
private void setLeftAndRightOffset(View child, int verticalOffset, float scale) {
ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper);
int maxOffsetDistance = getMaxOffset(viewHelper, scale);
int maxLeft = viewHelper.getLayoutLeft()
+ (viewHelper.getViewWidth() - viewHelper.getScaleViewWidth(scale))
- viewHelper.getMarginTitleLeft();
int realOffset = (int) (maxLeft * 1.0f / (maxOffsetDistance * 1.0f) * verticalOffset);
realOffset = constrain(realOffset, -maxLeft, maxLeft);
viewHelper.setLeftAndRightOffset(realOffset);
// Log.e("setLeftAndRightOffset",""+realOffset);
}
private void setViewScale(View child, int verticalOffset, float scale) {
ViewHelper viewHelper = (ViewHelper) child.getTag(R.id.view_helper);
int maxOffsetDistance = getMaxOffset(viewHelper, scale);
float realScale = -verticalOffset - maxOffsetDistance > 0 ? scale : verticalOffset == 0 ? 1f : 0f;
if (realScale == 0) {
realScale = (maxOffsetDistance + verticalOffset * (1 - scale)) / (maxOffsetDistance * 1f);
}
viewHelper.setViewOffsetScale(realScale);
}
private int getMaxOffset(ViewHelper viewHelper, float scale) {
int scaleViewHeight = (int) (scale * viewHelper.getViewHeight());
int offsetTitleDistance = scaleViewHeight >= mTitleHeight ? 0 : (mTitleHeight - scaleViewHeight) / 2;
int marginTop = viewHelper.getMarginTitleTop() >= offsetTitleDistance ? offsetTitleDistance : viewHelper.getMarginTitleTop();
return viewHelper.getLayoutBottom() - viewHelper.getScaleViewHeight(scale) - offsetTitleDistance - marginTop;
}
private class OffsetListenerImp implements AppBarLayout.OnOffsetChangedListener {
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (mTitle != null) {
setTopAndBottomOffset(mTitle, verticalOffset);
}
if (mText != null) {
setTopAndBottomOffset(mText, verticalOffset, mTextScale);
setLeftAndRightOffset(mText, verticalOffset, mTextScale);
setViewScale(mText, verticalOffset, mTextScale);
}
if (mImg != null) {
setTopAndBottomOffset(mImg, verticalOffset, mImgScale);
setLeftAndRightOffset(mImg, verticalOffset, mImgScale);
setViewScale(mImg, verticalOffset, mImgScale);
}
}
}
public void setImgTitleMarginTop(int top) {
if (mImg != null) {
getViewOffsetHelper(mImg).setMarginTitleTop(top);
}
}
public void setImgTitleMarginLeft(int left) {
if (mImg != null) {
getViewOffsetHelper(mImg).setMarginTitleLeft(left);
}
}
public void setTextTitleMarginTop(int top) {
if (mText != null) {
getViewOffsetHelper(mText).setMarginTitleTop(top);
}
}
public void setImgTextMarginLeft(int left) {
if (mText != null) {
getViewOffsetHelper(mText).setMarginTitleLeft(left);
}
}
}
Here is the content_scolling.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#cccccc"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="nczz.cn.helloworld.ScrollingActivity"
tools:showIn="#layout/activity_scrolling">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/large_text" />
</android.support.v4.widget.NestedScrollView>
Here is the java:
package nczz.cn.helloworld;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
public class ScrollingActivity extends Activity {
LinearLayout titleTxt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_scrolling);
initViews();
setTitleBarHeight();
}
private void initViews(){
titleTxt= (LinearLayout) findViewById(R.id.test_title);
}
private void setTitleBarHeight(){
WindowManager manager=getWindowManager();
int height=manager.getDefaultDisplay().getHeight();
ViewGroup.LayoutParams params=titleTxt.getLayoutParams();
params.height=height/12;
titleTxt.setLayoutParams(params);
}
}
i am not sure but u can use following code according to view inside nested scrollview
viewlayoutInsidescrollview.setNestedScrollingEnabled(false);
in java class
I have a problem with adding my surface view to a linear layout, I have tried the already available answers and still cant seem to figure it out. My aim is to render an animation at the bottom of my login screen when my the next button is clicked. I tried adding a linear Layout to the Screen and then adding my gameView object on to that.
This is the loginActivity and game View Class for clarity I've also added the xml.
`package com.example.Combat;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.*;
import android.os.Bundle;
import android.util.Log;
import android.view.*;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyActivity extends Activity {
/**
* Called when the activity is first created.
*/
public GameView gameView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//setting the font
Typeface myTypeFace = Typeface.createFromAsset(getAssets(),"Typo Oxin free promo.ttf");
TextView myTextView = (TextView) findViewById(R.id.nameTextView);
myTextView.setTypeface(myTypeFace);
gameView = new GameView(this);
// LinearLayout.LayoutParams lp =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// lp.gravity= Gravity.BOTTOM;
LinearLayout myLayout = new LinearLayout(this);
myLayout.findViewById(R.id.gameLayoutView);
myLayout.addView(gameView);
}
#Override
public void onResume(){
super.onResume();
gameView.resume();
}
#Override
protected void onPause(){
super.onPause();
gameView.pause();
}
public void beginMotion(View view) {
GameView.isMoving=!GameView.isMoving;
// startActivity(new Intent(getApplicationContext(),transitionActivity.class));
}
}
`
package com.example.Combat;
import android.content.Context;
import android.graphics.*;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by vmuser on 2017/05/05.
*/
public class GameView extends SurfaceView implements Runnable{
private Thread gameThread;
private SurfaceHolder ourHolder;
public static volatile boolean playing=false;
private Canvas canvas;
private Bitmap bitmapRunningMan;
public static boolean isMoving=false;
private float runSpeedPerSecond = 150;
//LinearLayout screen=(LinearLayout)findViewById(R.id.theScreen);
private float manXPos = 1020, manYPos = 950;
private int frameWidth = 230, frameHeight = 274;
private int frameCount = 6;
private int currentFrame = 0;
private long fps;
private long timeThisFrame;
private long lastFrameChangeTime = 0;
private int frameLengthInMillisecond = 60;
private Rect frameToDraw = new Rect(0, 0, frameWidth, frameHeight);
private RectF whereToDraw = new RectF(manXPos, manYPos, manXPos + frameWidth, frameHeight);
public GameView(Context context) {
super(context);
ourHolder = getHolder();
bitmapRunningMan = BitmapFactory.decodeResource(getResources(),
R.drawable.perfectsoldier);
bitmapRunningMan = Bitmap.createScaledBitmap(bitmapRunningMan,
frameWidth * frameCount, frameHeight, false);
}
#Override
public void run() {
while (playing) {
long startFrameTime = System.currentTimeMillis();
update();
this.draw();
Log.d("theOne","its Happennig");
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
public void update() {
if (isMoving) {
manXPos = manXPos - runSpeedPerSecond / fps;
if (manXPos > 0) {
//manYPos += (int) frameHeight;
//manXPos = 10;
isMoving=false;
}
if (manYPos + frameHeight > 0) {
// manYPos = 10;
isMoving=false;
}
}
}
public void manageCurrentFrame() {
long time = System.currentTimeMillis();
if (isMoving) {
if (time > lastFrameChangeTime + frameLengthInMillisecond) {
lastFrameChangeTime = time;
currentFrame++;
if (currentFrame >= frameCount) {
currentFrame = 0;
}
}
}
frameToDraw.left = currentFrame * frameWidth;
frameToDraw.right = frameToDraw.left + frameWidth;
}
public void draw() {
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
whereToDraw.set((int) manXPos, (int) manYPos, (int) manXPos
+ frameWidth, (int) manYPos + frameHeight);
manageCurrentFrame();
canvas.drawBitmap(bitmapRunningMan, frameToDraw, whereToDraw, null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch(InterruptedException e) {
Log.e("ERR", "Joining Thread");
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
// public boolean onTouchEvent(MotionEvent event) {
// switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
// case MotionEvent.ACTION_DOWN :
// isMoving = !isMoving;
// break;
// }
//
// return true;
// }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusableInTouchMode="true"
android:color="#000000"
android:weightSum="1" android:background="#ffffff" android:orientation="vertical"
android:id="#+id/theScreen">
<ImageView
android:layout_width="113dp"
android:layout_height="130dp"
android:src="#drawable/thelogo"
android:id="#+id/imageView" android:layout_gravity="center_horizontal"/>
<TextView
android:layout_width="145dp"
android:layout_height="49dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="combat"
android:textSize="30sp"
android:textColor="#000000"
android:id="#+id/nameTextView" android:layout_gravity="right" android:layout_weight="0.06"/>
<EditText
android:layout_width="270dp"
android:layout_height="wrap_content"
android:hint="Username"
android:textColorHint="#808080"
android:textColor="#22272a"
android:id="#+id/userNameEditText" android:layout_gravity="center_horizontal"/>
<Button
android:layout_width="261dp"
android:layout_height="wrap_content"
android:text="Next"
android:drawableRight="#drawable/thearrow"
android:textColor="#000000"
android:onClick="beginMotion"
android:id="#+id/NextButton" android:layout_gravity="center_horizontal" android:background="#638455"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Create an account"
android:id="#+id/textView" android:layout_gravity="center_horizontal" android:layout_weight="0.07"
android:textColor="#22272A"/>
<LinearLayout
android:id="#+id/gameLayoutView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
</LinearLayout>
</LinearLayout>
You haven't attached myLayout to the activity main layout that you earlier set on setContentView(R.layout.main).
Instead of:
LinearLayout myLayout = new LinearLayout(this);
myLayout.findViewById(R.id.gameLayoutView);
myLayout.addView(gameView);
You should write this:
LinearLayout myLayout = (LinearLayout) findViewById(R.id.gameLayoutView);
myLayout.addView(gameView);
I am working on a project where I need to design two vertical sliders as shown in the image below
I had developed code which working fine in a range of 0 to 100.
But I am not sure of how to convert it to 18 to 80
Here I am adding my class and view XML
any help is appreciated.
Following is my Layout
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
import android.widget.TextView;
import wedviser.com.wedviser.R;
/**
* Created by Focaloid on 29-12-2016.
*/
public class RangeBarVerticalAge extends RelativeLayout {
private static final int TOTAL_DIVISION_COUNT = 100;
private static final int MAX_CLICK_DURATION = 200;
public OnRangeBarChangeListener onRangeBarChangeListener;
private int inactiveColor;
private int activeColor;
private double heightParent;
private View viewFilterMain, viewThumbMin, viewThumbMax;
private RelativeLayout relFilterMin, relFilterMax;
private float startYMin, startYMax;
private float movedYMin, movedYMax;
private int initialHeightMin;
private float dTopMin, dTopMax;
private int currentHeightMin, currentHeightMax;
private double resultMin = 0.0;
private double resultMax = 100.0;
private View viewParent;
// private TextView tvFilterMin, tvFilterMax;
private Context context;
private long startClickTime;
private RelativeLayout relativeLayout;
private int minRange = 0, maxRange = 100;
private View viewInActiveTop, viewInActiveBottom;
public RangeBarVerticalAge(Context context) {
super(context);
this.context = context;
initialize(context);
}
public RangeBarVerticalAge(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RangeBarVerticalAge, 0, 0);
System.out.println(a.getIndexCount());
activeColor = a.getColor(R.styleable.RangeBarVerticalAge_activeColor, Color.parseColor("#007FFF"));
inactiveColor = a.getColor(R.styleable.RangeBarVerticalAge_inactiveColor, Color.parseColor("#808080"));
a.recycle();
initialize(context);
}
public RangeBarVerticalAge(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initialize(context);
}
public static float convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
private void initialize(Context context) {
inflate(context, R.layout.rangebar_age, this);
onRangeBarChangeListener = (OnRangeBarChangeListener) context;
onRangeBarChangeListener.onRangeBarChangeAge((int) resultMin, (int) resultMax);
relativeLayout = (RelativeLayout) findViewById(R.id.rel_main);
// tvFilterMin = (TextView) findViewById(R.id.tv_filter_min);
//tvFilterMax = (TextView) findViewById(R.id.tv_filter_max);
relFilterMin = (RelativeLayout) findViewById(R.id.rel_filter_min);
relFilterMax = (RelativeLayout) findViewById(R.id.rel_filter_max);
viewThumbMax = findViewById(R.id.oval_thumb_max);
viewThumbMin = findViewById(R.id.oval_thumb_min);
viewFilterMain = findViewById(R.id.filter_main_view);
viewParent = findViewById(R.id.view_filter_parent);
viewInActiveTop = findViewById(R.id.view_inactive_line_top);
viewInActiveBottom = findViewById(R.id.view_inactive_line_bottom);
init();
relFilterMin.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startYMin = event.getRawY();
// startClickTime = Calendar.getInstance().getTimeInMillis();
break;
case MotionEvent.ACTION_UP: {
// long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
// if (clickDuration < MAX_CLICK_DURATION) {
// //Click event triggered
//
// }
break;
}
case MotionEvent.ACTION_MOVE:
movedYMin = event.getRawY() - startYMin;
startYMin = event.getRawY();
if (v.getHeight() + movedYMin <= initialHeightMin || dTopMin + v.getHeight() + movedYMin >= dTopMax) {
currentHeightMin = v.getHeight();
getResultMin();
break;
}
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height += movedYMin;
v.setLayoutParams(layoutParams);
dTopMin = v.getY();
currentHeightMin = v.getHeight();
getResultMin();
break;
default:
return false;
}
return true;
}
});
relFilterMax.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startYMax = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
movedYMax = event.getRawY() - startYMax;
startYMax = event.getRawY();
if (v.getHeight() - movedYMax <= initialHeightMin || v.getY() + movedYMax <= currentHeightMin + dTopMin) {
currentHeightMax = v.getHeight();
getResultMax();
break;
}
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height -= movedYMax;
v.setLayoutParams(layoutParams);
dTopMax = v.getY();
currentHeightMax = v.getHeight();
getResultMax();
break;
default:
return false;
}
return true;
}
});
}
private void init() {
// ViewCompat.setElevation(tvFilterMin, 100f);
viewFilterMain.setBackgroundColor(activeColor);
viewInActiveBottom.setBackgroundColor(inactiveColor);
viewInActiveTop.setBackgroundColor(inactiveColor);
initialHeightMin = (int) convertDpToPixel(30, context);
final ViewTreeObserver viewTreeObserver = relativeLayout.getViewTreeObserver();
// if (viewTreeObserver.isAlive())
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
viewParent.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
viewParent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
dTopMin = relFilterMin.getY();
dTopMax = relFilterMax.getY();
currentHeightMin = relFilterMin.getHeight();
System.out.println("viewParentGetHeight:" + viewParent.getHeight());
heightParent = viewParent.getHeight() - 2 * initialHeightMin;
}
});
}
public void getResultMin() {
//Max
resultMin = Math.floor(100 * (Math.abs(currentHeightMin - initialHeightMin)) / heightParent);
//tvFilterMin.setText((int) resultMin + "");
onRangeBarChangeListener.onRangeBarChangeAge((int) resultMin, (int) resultMax);
}
public void getResultMax() {
resultMax = Math.floor(100 * (Math.abs(currentHeightMax - initialHeightMin)) / heightParent);
resultMax = Math.abs(resultMax - 100);
//tvFilterMax.setText(((int) resultMax + ""));
onRangeBarChangeListener.onRangeBarChangeAge((int) resultMin, (int) resultMax);
}
public int getMinimumProgress() {
return (int) resultMin;
}
public void setMinimumProgress(final int minProgress) {
if (minProgress >= 0 && minProgress < 100 && minProgress < resultMax) {
resultMin = minProgress;
viewParent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
viewParent.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
viewParent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
currentHeightMin = ((minProgress * (viewParent.getHeight() - 2 * initialHeightMin) / 100) + initialHeightMin);
ViewGroup.LayoutParams layoutParams = relFilterMin.getLayoutParams();
layoutParams.height = currentHeightMin;
relFilterMin.setLayoutParams(layoutParams);
}
});
//tvFilterMin.setText((int) resultMin + "");
onRangeBarChangeListener.onRangeBarChangeAge((int) resultMin, (int) resultMax);
}
}
public int getMaximumProgress() {
return (int) resultMax;
}
public void setMaximumProgress(final int maxProgress) {
if (maxProgress >= 0 && maxProgress <= 100 && maxProgress > resultMin) {
resultMax = maxProgress;
viewParent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
viewParent.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
viewParent.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
currentHeightMax = ((Math.abs(maxProgress - 100) * (viewParent.getHeight() - 2 * initialHeightMin) / 100) + initialHeightMin);
ViewGroup.LayoutParams layoutParams = relFilterMax.getLayoutParams();
layoutParams.height = currentHeightMax;
relFilterMax.setLayoutParams(layoutParams);
}
});
// tvFilterMax.setText((int) resultMax + "");
onRangeBarChangeListener.onRangeBarChangeAge((int) resultMin, (int) resultMax);
}
}
public interface OnRangeBarChangeListener {
void onRangeBarChangeAge(int min, int max);
}
}
Folowing is my XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rel_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:orientation="vertical"
android:animateLayoutChanges="true"
>
<View
android:id="#+id/view_filter_parent"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:clickable="false" />
<View
android:id="#+id/filter_main_view"
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_marginBottom="20dp"
android:layout_alignRight="#+id/rel_filter_min"
android:layout_alignEnd="#+id/rel_filter_min"
android:layout_marginRight="11dp"
android:layout_marginEnd="11dp"
android:background="#2196f3" />
<RelativeLayout
android:id="#+id/rel_filter_min"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_gravity="bottom"
>
<RelativeLayout
android:id="#+id/rel_filter_min_text"
android:layout_alignParentBottom="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:background="#android:color/transparent"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></RelativeLayout>
<View
android:id="#+id/view_inactive_line_top"
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:layout_alignLeft="#+id/oval_thumb_min"
android:layout_alignStart="#+id/oval_thumb_min"
android:layout_marginLeft="8.5dp"
android:layout_marginStart="8.5dp"
android:layout_marginBottom="10dp"
android:background="#808080" />
<View
android:id="#+id/oval_thumb_min"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_toRightOf="#+id/rel_filter_min_text"
android:layout_toEndOf="#+id/rel_filter_min_text"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="4dp"
android:background="#drawable/oval_shape"
/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/rel_filter_max"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignLeft="#+id/filter_main_view"
android:layout_alignParentBottom="true"
android:layout_alignStart="#+id/filter_main_view"
android:layout_gravity="bottom"
android:layout_marginLeft="-11dp"
android:layout_marginStart="-11dp">
<View
android:id="#+id/view_inactive_line_bottom"
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10.5dp"
android:layout_marginStart="10.5dp"
android:layout_marginTop="15dp"
android:background="#808080" />
<View
android:id="#+id/oval_thumb_max"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#drawable/oval_shape"
/>
</RelativeLayout>
</RelativeLayout>
I am using a floating action button in my activity. I have created a related layout with a black opacity background. I want it to appear when the floating action button is clicked. The relative layout will appear behind the action button to make it look prominent.
Here is my xml layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.paaltao.activity.HomeActivity">
<include
android:id="#+id/app_bar"
layout="#layout/app_bar" />
<it.neokree.materialtabs.MaterialTabHost
android:id="#+id/materialTabHost"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="#+id/app_bar"
app:accentColor="#color/greenMaterial"
app:hasIcons="true"
app:primaryColor="#color/primaryColor"
app:textColor="#color/white" />
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/materialTabHost" />
<RelativeLayout
android:id="#+id/white_opacity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/materialTabHost"
android:background="#color/black80"
android:visibility="gone" />
<com.paaltao.classes.FloatingActionsMenu
android:id="#+id/multiple_actions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end"
fab:fab_addButtonColorPressed="#color/white_pressed"
fab:fab_addButtonPlusIconColor="#color/white"
fab:fab_labelStyle="#style/menu_labels_style"
app:fab_addButtonColorNormal="#color/primaryColor">
<com.paaltao.classes.FloatingActionButton
android:id="#+id/action_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fab:fab_colorNormal="#color/white"
fab:fab_colorPressed="#color/white_pressed"
fab:fab_title="Action B" />
</com.paaltao.classes.FloatingActionsMenu>
</RelativeLayout>
I am basically trying to set visibility of the relative layout to View.VISIBLE in the floating action menu class which extends a view group. Now I am getting null pointer exception when I am setting the visibility as View.VISIBLE in the button's onClick event.
Here is my Java Code :
package com.paaltao.classes;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.paaltao.R;
import java.util.zip.Inflater;
public class FloatingActionsMenu extends ViewGroup {
public static final int EXPAND_UP = 0;
public static final int EXPAND_DOWN = 1;
public static final int EXPAND_LEFT = 2;
public static final int EXPAND_RIGHT = 3;
private static final int ANIMATION_DURATION = 300;
private static final float COLLAPSED_PLUS_ROTATION = 0f;
private static final float EXPANDED_PLUS_ROTATION = 90f + 45f;
private int mAddButtonPlusColor;
private int mAddButtonColorNormal;
private int mAddButtonColorPressed;
private int mAddButtonSize;
private boolean mAddButtonStrokeVisible;
private int mExpandDirection;
private int mButtonSpacing;
private int mLabelsMargin;
private int mLabelsVerticalOffset;
private boolean mExpanded;
private AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
private AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
private AddFloatingActionButton mAddButton;
private RotatingDrawable mRotatingDrawable;
private int mMaxButtonWidth;
private int mMaxButtonHeight;
private int mLabelsStyle;
private int mButtonsCount;
private OnFloatingActionsMenuUpdateListener mListener;
private RelativeLayout whiteOverlay;
public interface OnFloatingActionsMenuUpdateListener {
void onMenuExpanded();
void onMenuCollapsed();
}
public FloatingActionsMenu(Context context) {
this(context, null);
}
public FloatingActionsMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public FloatingActionsMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attributeSet) {
mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing) - getResources().getDimension(R.dimen.fab_shadow_radius) - getResources().getDimension(R.dimen.fab_shadow_offset));
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0);
mAddButtonPlusColor = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonPlusIconColor, getColor(android.R.color.white));
mAddButtonColorNormal = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorNormal, getColor(android.R.color.holo_blue_dark));
mAddButtonColorPressed = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorPressed, getColor(android.R.color.holo_blue_light));
mAddButtonSize = attr.getInt(R.styleable.FloatingActionsMenu_fab_addButtonSize, FloatingActionButton.SIZE_NORMAL);
mAddButtonStrokeVisible = attr.getBoolean(R.styleable.FloatingActionsMenu_fab_addButtonStrokeVisible, true);
mExpandDirection = attr.getInt(R.styleable.FloatingActionsMenu_fab_expandDirection, EXPAND_UP);
mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionsMenu_fab_labelStyle, 0);
attr.recycle();
if (mLabelsStyle != 0 && expandsHorizontally()) {
throw new IllegalStateException("Action labels in horizontal expand orientation is not supported.");
}
createAddButton(context);
}
public void setOnFloatingActionsMenuUpdateListener(OnFloatingActionsMenuUpdateListener listener) {
mListener = listener;
}
private boolean expandsHorizontally() {
return mExpandDirection == EXPAND_LEFT || mExpandDirection == EXPAND_RIGHT;
}
private static class RotatingDrawable extends LayerDrawable {
public RotatingDrawable(Drawable drawable) {
super(new Drawable[] { drawable });
}
private float mRotation;
#SuppressWarnings("UnusedDeclaration")
public float getRotation() {
return mRotation;
}
#SuppressWarnings("UnusedDeclaration")
public void setRotation(float rotation) {
mRotation = rotation;
invalidateSelf();
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.rotate(mRotation, getBounds().centerX(), getBounds().centerY());
super.draw(canvas);
canvas.restore();
}
}
private void createAddButton(Context context) {
mAddButton = new AddFloatingActionButton(context) {
#Override
void updateBackground() {
mPlusColor = mAddButtonPlusColor;
mColorNormal = mAddButtonColorNormal;
mColorPressed = mAddButtonColorPressed;
mStrokeVisible = mAddButtonStrokeVisible;
super.updateBackground();
}
#Override
Drawable getIconDrawable() {
final RotatingDrawable rotatingDrawable = new RotatingDrawable(super.getIconDrawable());
mRotatingDrawable = rotatingDrawable;
final OvershootInterpolator interpolator = new OvershootInterpolator();
final ObjectAnimator collapseAnimator = ObjectAnimator.ofFloat(rotatingDrawable, "rotation", EXPANDED_PLUS_ROTATION, COLLAPSED_PLUS_ROTATION);
final ObjectAnimator expandAnimator = ObjectAnimator.ofFloat(rotatingDrawable, "rotation", COLLAPSED_PLUS_ROTATION, EXPANDED_PLUS_ROTATION);
collapseAnimator.setInterpolator(interpolator);
expandAnimator.setInterpolator(interpolator);
mExpandAnimation.play(expandAnimator);
mCollapseAnimation.play(collapseAnimator);
return rotatingDrawable;
}
};
mAddButton.setId(R.id.fab_expand_menu_button);
mAddButton.setSize(mAddButtonSize);
mAddButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
toggle();
// updateBackground();
}
});
addView(mAddButton, super.generateDefaultLayoutParams());
}
// public void updateBackground(){
// whiteOverlay = (RelativeLayout)findViewById(R.id.white_opacity);
// whiteOverlay.setVisibility(View.VISIBLE);
// }
public void addButton(FloatingActionButton button) {
addView(button, mButtonsCount - 1);
mButtonsCount++;
if (mLabelsStyle != 0) {
createLabels();
}
}
public void removeButton(FloatingActionButton button) {
removeView(button.getLabelView());
removeView(button);
mButtonsCount--;
}
private int getColor(#ColorRes int id) {
return getResources().getColor(id);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int width = 0;
int height = 0;
mMaxButtonWidth = 0;
mMaxButtonHeight = 0;
int maxLabelWidth = 0;
for (int i = 0; i < mButtonsCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
switch (mExpandDirection) {
case EXPAND_UP:
case EXPAND_DOWN:
mMaxButtonWidth = Math.max(mMaxButtonWidth, child.getMeasuredWidth());
height += child.getMeasuredHeight();
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
width += child.getMeasuredWidth();
mMaxButtonHeight = Math.max(mMaxButtonHeight, child.getMeasuredHeight());
break;
}
if (!expandsHorizontally()) {
TextView label = (TextView) child.getTag(R.id.fab_label);
if (label != null) {
maxLabelWidth = Math.max(maxLabelWidth, label.getMeasuredWidth());
}
}
}
if (!expandsHorizontally()) {
width = mMaxButtonWidth + (maxLabelWidth > 0 ? maxLabelWidth + mLabelsMargin : 0);
} else {
height = mMaxButtonHeight;
}
switch (mExpandDirection) {
case EXPAND_UP:
case EXPAND_DOWN:
height += mButtonSpacing * (getChildCount() - 1);
height = adjustForOvershoot(height);
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
width += mButtonSpacing * (getChildCount() - 1);
width = adjustForOvershoot(width);
break;
}
setMeasuredDimension(width, height);
}
private int adjustForOvershoot(int dimension) {
return dimension * 12 / 10;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
switch (mExpandDirection) {
case EXPAND_UP:
case EXPAND_DOWN:
boolean expandUp = mExpandDirection == EXPAND_UP;
int addButtonY = expandUp ? b - t - mAddButton.getMeasuredHeight() : 0;
// Ensure mAddButton is centered on the line where the buttons should be
int addButtonLeft = r - l - mMaxButtonWidth + (mMaxButtonWidth - mAddButton.getMeasuredWidth()) / 2;
mAddButton.layout(addButtonLeft, addButtonY, addButtonLeft + mAddButton.getMeasuredWidth(), addButtonY + mAddButton.getMeasuredHeight());
int labelsRight = r - l - mMaxButtonWidth - mLabelsMargin;
int nextY = expandUp ?
addButtonY - mButtonSpacing :
addButtonY + mAddButton.getMeasuredHeight() + mButtonSpacing;
for (int i = mButtonsCount - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child == mAddButton || child.getVisibility() == GONE) continue;
int childX = addButtonLeft + (mAddButton.getMeasuredWidth() - child.getMeasuredWidth()) / 2;
int childY = expandUp ? nextY - child.getMeasuredHeight() : nextY;
child.layout(childX, childY, childX + child.getMeasuredWidth(), childY + child.getMeasuredHeight());
float collapsedTranslation = addButtonY - childY;
float expandedTranslation = 0f;
child.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation);
child.setAlpha(mExpanded ? 1f : 0f);
LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation);
params.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation);
params.setAnimationsTarget(child);
View label = (View) child.getTag(R.id.fab_label);
if (label != null) {
int labelLeft = labelsRight - label.getMeasuredWidth();
int labelTop = childY - mLabelsVerticalOffset + (child.getMeasuredHeight() - label.getMeasuredHeight()) / 2;
label.layout(labelLeft, labelTop, labelsRight, labelTop + label.getMeasuredHeight());
label.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation);
label.setAlpha(mExpanded ? 1f : 0f);
LayoutParams labelParams = (LayoutParams) label.getLayoutParams();
labelParams.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation);
labelParams.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation);
labelParams.setAnimationsTarget(label);
}
nextY = expandUp ?
childY - mButtonSpacing :
childY + child.getMeasuredHeight() + mButtonSpacing;
}
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
boolean expandLeft = mExpandDirection == EXPAND_LEFT;
int addButtonX = expandLeft ? r - l - mAddButton.getMeasuredWidth() : 0;
// Ensure mAddButton is centered on the line where the buttons should be
int addButtonTop = b - t - mMaxButtonHeight + (mMaxButtonHeight - mAddButton.getMeasuredHeight()) / 2;
mAddButton.layout(addButtonX, addButtonTop, addButtonX + mAddButton.getMeasuredWidth(), addButtonTop + mAddButton.getMeasuredHeight());
int nextX = expandLeft ?
addButtonX - mButtonSpacing :
addButtonX + mAddButton.getMeasuredWidth() + mButtonSpacing;
for (int i = mButtonsCount - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child == mAddButton || child.getVisibility() == GONE) continue;
int childX = expandLeft ? nextX - child.getMeasuredWidth() : nextX;
int childY = addButtonTop + (mAddButton.getMeasuredHeight() - child.getMeasuredHeight()) / 2;
child.layout(childX, childY, childX + child.getMeasuredWidth(), childY + child.getMeasuredHeight());
float collapsedTranslation = addButtonX - childX;
float expandedTranslation = 0f;
child.setTranslationX(mExpanded ? expandedTranslation : collapsedTranslation);
child.setAlpha(mExpanded ? 1f : 0f);
LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation);
params.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation);
params.setAnimationsTarget(child);
nextX = expandLeft ?
childX - mButtonSpacing :
childX + child.getMeasuredWidth() + mButtonSpacing;
}
break;
}
}
#Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(super.generateDefaultLayoutParams());
}
#Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(super.generateLayoutParams(attrs));
}
#Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(super.generateLayoutParams(p));
}
#Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return super.checkLayoutParams(p);
}
private static Interpolator sExpandInterpolator = new OvershootInterpolator();
private static Interpolator sCollapseInterpolator = new DecelerateInterpolator(3f);
private static Interpolator sAlphaExpandInterpolator = new DecelerateInterpolator();
private class LayoutParams extends ViewGroup.LayoutParams {
private ObjectAnimator mExpandDir = new ObjectAnimator();
private ObjectAnimator mExpandAlpha = new ObjectAnimator();
private ObjectAnimator mCollapseDir = new ObjectAnimator();
private ObjectAnimator mCollapseAlpha = new ObjectAnimator();
private boolean animationsSetToPlay;
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
mExpandDir.setInterpolator(sExpandInterpolator);
mExpandAlpha.setInterpolator(sAlphaExpandInterpolator);
mCollapseDir.setInterpolator(sCollapseInterpolator);
mCollapseAlpha.setInterpolator(sCollapseInterpolator);
mCollapseAlpha.setProperty(View.ALPHA);
mCollapseAlpha.setFloatValues(1f, 0f);
mExpandAlpha.setProperty(View.ALPHA);
mExpandAlpha.setFloatValues(0f, 1f);
switch (mExpandDirection) {
case EXPAND_UP:
case EXPAND_DOWN:
mCollapseDir.setProperty(View.TRANSLATION_Y);
mExpandDir.setProperty(View.TRANSLATION_Y);
break;
case EXPAND_LEFT:
case EXPAND_RIGHT:
mCollapseDir.setProperty(View.TRANSLATION_X);
mExpandDir.setProperty(View.TRANSLATION_X);
break;
}
}
public void setAnimationsTarget(View view) {
mCollapseAlpha.setTarget(view);
mCollapseDir.setTarget(view);
mExpandAlpha.setTarget(view);
mExpandDir.setTarget(view);
// Now that the animations have targets, set them to be played
if (!animationsSetToPlay) {
mCollapseAnimation.play(mCollapseAlpha);
mCollapseAnimation.play(mCollapseDir);
mExpandAnimation.play(mExpandAlpha);
mExpandAnimation.play(mExpandDir);
animationsSetToPlay = true;
}
}
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
bringChildToFront(mAddButton);
mButtonsCount = getChildCount();
if (mLabelsStyle != 0) {
createLabels();
}
}
private void createLabels() {
Context context = new ContextThemeWrapper(getContext(), mLabelsStyle);
for (int i = 0; i < mButtonsCount; i++) {
FloatingActionButton button = (FloatingActionButton) getChildAt(i);
String title = button.getTitle();
if (button == mAddButton || title == null ||
button.getTag(R.id.fab_label) != null) continue;
TextView label = new TextView(context);
label.setText(button.getTitle());
addView(label);
button.setTag(R.id.fab_label, label);
}
}
public void collapse() {
if (mExpanded) {
mExpanded = false;
mCollapseAnimation.start();
mExpandAnimation.cancel();
if (mListener != null) {
mListener.onMenuCollapsed();
}
}
}
public void toggle() {
if (mExpanded) {
collapse();
} else {
expand();
}
}
public void expand() {
if (!mExpanded) {
mExpanded = true;
mCollapseAnimation.cancel();
mExpandAnimation.start();
if (mListener != null) {
mListener.onMenuExpanded();
}
}
}
public boolean isExpanded() {
return mExpanded;
}
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.mExpanded = mExpanded;
return savedState;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof SavedState) {
SavedState savedState = (SavedState) state;
mExpanded = savedState.mExpanded;
if (mRotatingDrawable != null) {
mRotatingDrawable.setRotation(mExpanded ? EXPANDED_PLUS_ROTATION : COLLAPSED_PLUS_ROTATION);
}
super.onRestoreInstanceState(savedState.getSuperState());
} else {
super.onRestoreInstanceState(state);
}
}
public static class SavedState extends BaseSavedState {
public boolean mExpanded;
public SavedState(Parcelable parcel) {
super(parcel);
}
private SavedState(Parcel in) {
super(in);
mExpanded = in.readInt() == 1;
}
#Override
public void writeToParcel(#NonNull Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(mExpanded ? 1 : 0);
}
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
Please Help.
If I understand correctly, the code causing the problem is the one commented, otherwise this line :
whiteOverlay.setVisibility(View.VISIBLE);
You are trying to access your RelativeLayout (R.id.white_opacity) through your FloatingActionsMenu view :
whiteOverlay = (RelativeLayout)findViewById(R.id.white_opacity);
But R.id.white_opacity is a member of your HomeActivity view.
So it's normal that this line returns a null pointer since it doesn't have any member named like this.
Try do find a way to access your HomeActivity view and then call "findViewById()" on it.
If "context" is indeed this HomeActivity, then pass the argument to the updateBackground() method (or set context as a class member) and try somthing like that :
whiteOverlay = ((Activity)context).findViewById(R.id.white_opacity);
Regards.