i have a library to insert floating buttons in a layout (http://prolificinteractive.com/blog/2014/07/24/android-floating-action-button-aka-fab/)
Then, i have this layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fontawesometext="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp">
<com.beardedhen.androidbootstrap.FontAwesomeText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="4dp"
android:textSize="45sp"
android:textColor="#737373"
android:id="#+id/faIcon"
fontawesometext:fa_icon="fa-question" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text='"texto de ejemplo de pregunta"'
android:id="#+id/tvQuestion"
android:textColor="#color/primary"
android:textStyle="bold"
android:textSize="28sp"
android:typeface="monospace"
android:layout_marginLeft="16dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16sp" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/frameConainter"
android:background="#color/dark_grey" />
</LinearLayout>
And i need to set the center of the button in the middle of framelayout top, like as the left image:
I have this in a custom view:
public class YesNoReplyView extends ReplyParentView {
private FloatingActionButton buttonYes;
private FloatingActionButton buttonNo;
public YesNoReplyView(Context context) {
super(context);
}
public YesNoReplyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public YesNoReplyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void initializeComponents() {
int[] position = new int[2];
getLocationOnScreen(position);
buttonYes = new FloatingActionButton.Builder((Activity)getContext())
.withDrawable(getResources().getDrawable(R.drawable.ic_plus))
.withButtonColor(getResources().getColor(R.color.green_success))
.withGravity(Gravity.BOTTOM | Gravity.RIGHT)
.withMargins(0, 0, 16, 16)
.create();
buttonNo = new FloatingActionButton.Builder((Activity)getContext())
.withDrawable(getResources().getDrawable(R.drawable.ic_plus))
.withButtonColor(getResources().getColor(R.color.primary))
.withGravity(Gravity.BOTTOM | Gravity.RIGHT)
.withMargins(0, 0, 26, 26)
.create();
}
#Override
public String getResult() {
String result = "";
return result;
}
}
But i dont know how can i calculate the margins from the coordinates to set the view in the position i want..
Anyone knows any way better to do it this?(I cant use a XML layout..)
Related
I'm working in Android Studio on a project, which has a quiz game with either images or text as answer options, depending on the question (both are just buttons in the xml file). Currently these buttons are shown in 2 columns but in case the buttons are displaying text instead of images the column count should be 1 because the button size has to be wider to show the whole text.
In my adapter the onBindViewHolder gets a list of answer options and sets the button content based on the option type (images/text). For some testing I've created the subclass AutofitRecyclerView of RecylerView to compute the number of columns automatically but that didn't solve my issue. Inside the AutofitRecyclerView I definded a CenteredGridLayoutManager. Furthermore I experimented with the method setSpanSizeLookup but that also didn't help.
AutofitRecyclerView:
public class AutofitRecyclerView extends RecyclerView {
private GridLayoutManager manager;
private int columnWidth = -1;
public AutofitRecyclerView(Context context) {
super(context);
init(context, null);
}
public AutofitRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
manager = new CenteredGridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (columnWidth > 0) {
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
manager.setSpanCount(spanCount);
}
}
private class CenteredGridLayoutManager extends GridLayoutManager {
public CenteredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CenteredGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
public CenteredGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
#Override
public int getPaddingLeft() {
final int totalItemWidth = columnWidth * getSpanCount();
if (totalItemWidth >= AutofitRecyclerView.this.getMeasuredWidth()) {
return super.getPaddingLeft(); // do nothing
} else {
return Math.round((AutofitRecyclerView.this.getMeasuredWidth() / (1f + getSpanCount())) - (totalItemWidth / (1f + getSpanCount())));
}
}
#Override
public int getPaddingRight() {
return getPaddingLeft();
}
}
}
Button-XML-File:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="14dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout_imgButton"
android:layout_width="125dp"
android:layout_height="125dp"
android:layout_marginBottom="0dp"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/option_imgButton"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="#string/game_choose_answer_option_button_placeholder_text"
app:layout_constraintBottom_toBottomOf="#id/constraintLayout_imgButton"
app:layout_constraintEnd_toEndOf="#id/constraintLayout_imgButton"
app:layout_constraintStart_toStartOf="#id/constraintLayout_imgButton"
app:layout_constraintTop_toTopOf="#id/constraintLayout_imgButton" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout_txtButton"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_gravity="fill_horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/option_textButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#drawable/button_background"
android:elevation="4dp"
android:fontFamily="#font/freude"
android:stateListAnimator="#null"
android:text="#string/game_choose_answer_option_button_placeholder_text"
android:textAppearance="#style/TextAppearance.Compat.Notification.Title.Media"
android:textColor="#color/forest"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="#id/constraintLayout_txtButton"
app:layout_constraintEnd_toEndOf="#id/constraintLayout_txtButton"
app:layout_constraintStart_toStartOf="#id/constraintLayout_txtButton"
app:layout_constraintTop_toTopOf="#id/constraintLayout_txtButton" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Recyclerview-XML-File:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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="de.lmu.treeapp.activities.minigames.chooseAnswer.GameActivity_ChooseAnswer">
<TextView
android:id="#+id/game_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:text="#string/game_description_placeholder"
app:layout_constraintTop_toTopOf="#+id/guideline_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.04" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.02" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.98" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.02" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline_mid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.3" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline_bot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.98" />
<de.lmu.treeapp.activities.minigames.chooseAnswer.AutofitRecyclerView
android:id="#+id/auto_fit_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="20dp"
android:clipToPadding="false"
android:columnWidth="150dp"
android:numColumns="auto_fit"
app:layout_constraintBottom_toBottomOf="#id/guideline_bot"
app:layout_constraintEnd_toEndOf="#id/guideline_right"
app:layout_constraintStart_toStartOf="#id/guideline_left"
app:layout_constraintTop_toBottomOf="#+id/guideline_mid" />
</androidx.constraintlayout.widget.ConstraintLayout>
What else can I do which I havn't seen right now? It may be better to provide 2 different xml layouts for the 2 different buttons, but I don't know how I can tell my recyclerView which layout xml it has to take.
You could use a framelayout and put both buttons in it and make both buttons gone. A framelayout would only display one single view so if the answer is a text you can only make the text button visible else you make the imagebutton visible.
Finally found a way to determine the column number. Inside my adapter class, I wrote a method which gets a list of the current answer options and returns true if the type is image. In the AutofitRecyclerView class I replaced the method onMeasure with the following code in order to set the spanCount to either 1 or 2:
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (columnWidth > 0) {
int spanCount;
if(RecyclerViewAdapter.isImage(RecyclerViewAdapter.options)){
spanCount = 2;
} else spanCount = 1;
manager.setSpanCount(spanCount);
}
}
While I was testing around I've found out that it is very important to set a default value for spanCount before the method onMeasure computes new values.
Additionally I removed the CenteredGridLayoutManager and replaced it with just GridLayoutManager because my buttons already are centered.
Thanks anyway #Fadman, the FrameLayout helped me a lot. With the other layout my text buttons were shown with large white space between them because the invisible image buttons were also inside the respective container.
Layout xml of buttons:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="14dp"
android:id="#+id/option_frame_layout">
<Button
android:id="#+id/button_img"
android:layout_width="125dp"
android:layout_height="125dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:visibility="gone"/>
<Button
android:id="#+id/button_txt"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#drawable/button_background"
android:elevation="4dp"
android:fontFamily="#font/freude"
android:stateListAnimator="#null"
android:text="#string/game_choose_answer_option_button_placeholder_text"
android:textAppearance="#style/TextAppearance.Compat.Notification.Title.Media"
android:textColor="#color/forest"
android:textSize="20sp"
android:visibility="gone" />
</FrameLayout>
The visibility of both buttons is set to gone and will be changed in the code at runtime.
Use--> app:spanCount="3"
enter image description here
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
app:spanCount="3"
app:layoutManager="StaggeredGridLayoutManager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scrollbars="vertical"
/>
I have recycler view which uses grid layout manager to show items in 2 columns like this:
If you notice the image bottom margin is different for left row. In the item layout the image view has property "alignparentbottom=true", but all the items in the left row have this wrong margin at bottom (png file has no margin, I have verified.). I have extended RelativeLayout to make it square shaped like this:
public class SquareRelativeLayout extends RelativeLayout {
private static final int HEIGHT_RATIO = 1;
private static final int WIDTH_RATIO = 1;
public SquareRelativeLayout(Context context) {
super(context);
}
public SquareRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Set a square layout.
/*int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = (int) (HEIGHT_RATIO / WIDTH_RATIO * widthSize);
int newHeightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);*/
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
Here is the whole item layout:
<?xml version="1.0" encoding="utf-8"?>
<com.org.framework.ui.widget.SquareRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/transparent_round_rect"
android:layout_marginTop="#dimen/margin_16" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/ll_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="20"
android:layout_marginTop="#dimen/margin_12"
android:layout_marginRight="#dimen/margin_12"
android:layout_marginLeft="#dimen/margin_12">
<TextView
android:id="#+id/tv_wallet_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="15"
style="#style/SmallWhiteText"
android:text="Reimbursement"
android:ellipsize="end"
android:lines="1"
android:maxLines="1" />
<RadioButton
android:id="#+id/rb_select"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:layout_marginTop="-3dp"
android:layout_gravity="end|center_vertical"
android:buttonTint="#color/white" />
</LinearLayout>
<TextView
android:id="#+id/tv_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/LargeWhiteText"
android:text="2000"
android:layout_marginRight="#dimen/margin_12"
android:layout_marginLeft="#dimen/margin_12"
android:layout_below="#id/ll_top"/>
<ImageView
android:id="#+id/iv_wallet_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/gift"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
/>
<!--android:layout_marginRight="-1.5dp"
android:layout_marginBottom="-7dp"-->
<FrameLayout
android:id="#+id/fl_na"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#435977"
android:layout_alignParentBottom="true"
android:padding="5dp"
android:visibility="gone">
<TextView
android:id="#+id/tv_not_applicable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/text_not_applicable"
style="#style/VerySmallWhiteText"
android:layout_gravity="center_horizontal"/>
</FrameLayout>
</RelativeLayout>
</com.org.framework.ui.widget.SquareRelativeLayout>
First- Items shouldn't have different bottom margins for left and right columns. What's the reason?
second- I have tried to programatically fix the layout inside onBindViewHolder method (with/without layout tree observer) like this:
ViewTreeObserver tob = uvh.rlRoot.getViewTreeObserver();
tob.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
uvh.rlRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Log.e("flNa", (uvh.flNa.getTop()+uvh.flNa.getHeight())+",");
Log.e("ivWallet", (uvh.ivLogo.getTop()+uvh.ivLogo.getHeight())+",");
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) uvh.ivLogo.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
//params.bottomMargin = 0;
//uvh.ivLogo.setBottom(-10);
uvh.ivLogo.setTop(uvh.rlRoot.getHeight()-uvh.ivLogo.getHeight());
uvh.ivLogo.setLayoutParams(params);
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) uvh.flNa.getLayoutParams();
params1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
params1.bottomMargin = 1;
uvh.flNa.setLayoutParams(params1);
uvh.rlRoot.forceLayout();
uvh.rlRoot.invalidate();
uvh.rlRoot.requestLayout();
}
});
This has no effect on layout.
How to fix this issue?
I have my custom BottomSheetDialogFragment.Inside this dialog I have custom edittext and recyclerview.My goal is to move reyclerview above a keyboard,when it' showing. Here is a my custom edittext code
public class WrappedEditText extends android.support.v7.widget.AppCompatEditText {
public WrappedEditText(Context context) {
super(context);
}
public WrappedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrappedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Nullable
private View wrapper;
#Nullable
public View getWrapper() {
return wrapper;
}
#Override
public void getFocusedRect(Rect r) {
if (wrapper != null) {
wrapper.getFocusedRect(r);
return;
}
super.getFocusedRect(r);
}
#Override
public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
if (wrapper != null)
return wrapper.getGlobalVisibleRect(r, globalOffset);
return super.getGlobalVisibleRect(r, globalOffset);
}
public void setWrapper(#Nullable View wrapper) {
this.wrapper = wrapper;
}
I'm using this code like this
searchView.setWrapper(rootView);
searchView.setOnFocusChangeListener((view1, b) -> {
if(searchView.getWrapper()==null)
searchView.setWrapper(rootView);
});
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#drawable/slide_menu_background"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/close_view"
android:layout_width="wrap_content"
android:layout_height="#dimen/dimen_p_30"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:orientation="vertical">
<View
android:layout_width="#dimen/dimen_p_40"
android:layout_height="#dimen/dimen_p_4"
android:layout_alignParentTop="true"
android:layout_marginTop="#dimen/dimen_p_10"
android:background="#drawable/slide_menu_title_line" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/title_conainer"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_p_30"
android:layout_below="#+id/close_view">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/dimen_p_30"
android:fontFamily="#font/myriad_geo_medium"
android:text="#string/insert_gif"
android:textColor="#color/black"
android:textSize="#dimen/dimen_p_14" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/search_layout"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_p_38"
android:layout_below="#+id/title_conainer"
android:layout_marginLeft="#dimen/dimen_p_30"
android:layout_marginRight="#dimen/dimen_p_30"
android:background="#drawable/rounded_corners_white">
<ImageView
android:id="#+id/search_icon"
android:layout_width="#dimen/dimen_p_24"
android:layout_height="#dimen/dimen_p_24"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/dimen_p_8"
android:background="#mipmap/search_icon" />
<app.singltone.giphy.WrappedEditText
android:id="#+id/search_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/dimen_p_35"
android:layout_marginRight="#dimen/dimen_p_10"
android:background="#null"
android:fontFamily="#font/myriad_geo_medium"
android:gravity="center_vertical"
android:hint="#string/find_gif"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:singleLine="true"
android:textColor="#color/black"
android:textColorHint="#59000000"
android:textSize="#dimen/dimen_p_14" />
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/search_layout"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:saveEnabled="true" />
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
rootView is a main view in xml file.This code working perfect only first time,but when user closed keyboard and then opened it again ,this code does not working.
Is a any way to solve this problem? or is this a correct solution?
Thanks
I'm making a music player and have implemented a marquee for the song and artist name. But as soon as the seek bar gets updated, the text view comes back to the original position. So in this way, a kind of back and forth motion of text is seen.
Here is my XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:id="#+id/mainFullPlayerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.musicplayer.integrated.sanket.music.MainFullPlayer"
android:background="#color/defaultBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/relativeLayout"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<ImageView
android:id="#+id/imageView_full_player_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="20dp"
android:layout_marginRight="15dp"
app:srcCompat="#drawable/icon_more" />
</RelativeLayout>
<ImageView
android:id="#+id/imageView_full_player_album_art"
android:layout_width="300dp"
android:layout_height="300dp"
app:srcCompat="#drawable/default_album_art"
android:layout_marginTop="29dp"
android:layout_below="#+id/relativeLayout"
android:layout_centerHorizontal="true" />
<SeekBar
android:id="#+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressTint="#color/defaultTextColor"
android:thumbTint="#color/defaultTextColor"
android:layout_above="#+id/imageView_full_player_play"
android:layout_marginBottom="37dp" />
<ImageView
android:id="#+id/imageView_full_player_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="31dp"
app:srcCompat="#drawable/icon_play_small" />
<ImageView
android:id="#+id/imageView_full_player_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imageView_full_player_play"
android:layout_marginStart="39dp"
android:layout_toEndOf="#+id/imageView_full_player_play"
app:srcCompat="#drawable/icon_fast_next_small" />
<ImageView
android:id="#+id/imageView_full_player_prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imageView_full_player_play"
android:layout_marginEnd="38dp"
android:layout_toStartOf="#+id/imageView_full_player_play"
app:srcCompat="#drawable/icon_rewind_prev_small" />
<TextView
android:id="#+id/textView_full_player_song"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/imageView_full_player_album_art"
android:layout_alignStart="#+id/imageView_full_player_album_art"
android:layout_below="#+id/imageView_full_player_album_art"
android:layout_marginTop="12dp"
android:ellipsize="marquee"
android:focusable="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="Song Name"
android:textAlignment="center"
android:textColor="#color/defaultTextColor"
android:textSize="18sp" />
<TextView
android:id="#+id/textView_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0:00"
android:textColor="#color/defaultTextColor"
android:textSize="12sp"
android:layout_marginBottom="18dp"
android:layout_above="#+id/imageView_full_player_prev"
android:layout_alignStart="#+id/textView_full_player_artist" />
<TextView
android:id="#+id/textView_total_length"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5:00"
android:textSize="12sp"
android:textColor="#color/defaultTextColor"
android:layout_alignBaseline="#+id/textView_current_time"
android:layout_alignBottom="#+id/textView_current_time"
android:layout_alignEnd="#+id/textView_full_player_artist" />
<TextView
android:id="#+id/textView_full_player_artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/textView_full_player_song"
android:layout_alignStart="#+id/textView_full_player_song"
android:layout_below="#+id/textView_full_player_song"
android:layout_marginTop="12dp"
android:text="Artist"
android:textAlignment="center"
android:textColor="#color/defaultTextColor"
android:textSize="15sp"
android:ellipsize="marquee"
android:singleLine="true"
android:marqueeRepeatLimit="marquee_forever"
android:focusable="true"
android:scrollHorizontally="true"
/>
</RelativeLayout>
Here is my Java code:
public class MainFullPlayer extends AppCompatActivity {
private static RelativeLayout fullPlayer;
private static ImageView fullPlayer_play , fullPlayer_next ,
fullPlayer_prev,fullPlayer_album;
private static TextView fullPlayer_song , fullPlayer_artist ,
fullPlayer_currentTime , fullPlayer_maxTime;
private static SeekBar seekBar;
private Songs song;
private static Handler progressHandler;
private static Runnable progressRunnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_full_player);
fullPlayer = (RelativeLayout)findViewById(R.id.mainFullPlayerContainer);
fullPlayer_play = (ImageView)findViewById(R.id.imageView_full_player_play);
fullPlayer_next = (ImageView)findViewById(R.id.imageView_full_player_next);
fullPlayer_prev = (ImageView)findViewById(R.id.imageView_full_player_prev);
fullPlayer_album = (ImageView)findViewById(R.id.imageView_full_player_album_art);
fullPlayer_song = (TextView)findViewById(R.id.textView_full_player_song);
fullPlayer_artist = (TextView)findViewById(R.id.textView_full_player_artist);
fullPlayer_currentTime = (TextView)findViewById(R.id.textView_current_time);
fullPlayer_maxTime = (TextView)findViewById(R.id.textView_total_length);
fullPlayer_maxTime.setText(MusicPlayback.getTime(MusicPlayback.mediaPlayer.getDuration()));
seekBar = (SeekBar)findViewById(R.id.seekBar);
song = MusicPlayback.allTracks.get(MusicPlayback.songPosition);
fullPlayer_song.setSelected(true);
fullPlayer_artist.setSelected(true);
fullPlayer_song.setText(song.getSongName());
fullPlayer_artist.setText(song.getArtist());
if(MusicPlayback.getPlayingStatus()){
fullPlayer_play.setImageResource(R.drawable.icon_pause_small);
}
else
{
fullPlayer_play.setImageResource(R.drawable.icon_play_small);
}
if(song.getAlbumArt()!= null){
fullPlayer_album.setImageURI(Uri.parse(song.getAlbumArt()));
fullPlayer.setBackground(FragmentAllTracks.d);
}
else{
fullPlayer_album.setImageResource(R.drawable.default_album_art);
fullPlayer.setBackgroundColor(Color.argb(255, 48, 48, 48));
}
seekBar.setMax(MusicPlayback.mediaPlayer.getDuration());
progressHandler = new Handler();
progressRunnable = new Runnable() {
#Override
public void run() {
seekBar.setProgress(MusicPlayback.mediaPlayer.getCurrentPosition());
fullPlayer_currentTime.setText(MusicPlayback.getTime(MusicPlayback.mediaPlayer.getCurrentPosition()));
progressHandler.postDelayed(progressRunnable,100);
}
};
progressHandler.postDelayed(progressRunnable,100);
}
#Override
public void onBackPressed() {
super.onBackPressed();
this.overridePendingTransition(R.anim.left_exit_translate,R.anim.right_exit_translate);
}
}
Here is the result:
Try to use this MarqueeTextView class, it automatically set fixed size for TextView so it won't re-measure (the reason cause restart scroll animation):
public class MarqueeTextView extends AppCompatTextView implements View.OnLayoutChangeListener {
public MarqueeTextView(Context context) {
this(context, null);
}
public MarqueeTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setSingleLine();
setEllipsize(TextUtils.TruncateAt.MARQUEE);
setMarqueeRepeatLimit(-1);
setSelected(true);
addOnLayoutChangeListener(this);
}
#Override
public boolean isFocused() {
return true;
}
#Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (hasWindowFocus) super.onWindowFocusChanged(hasWindowFocus);
}
#Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (focused) super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = bottom - top;
layoutParams.width = right - left;
removeOnLayoutChangeListener(this);
setLayoutParams(layoutParams);
}
}
I had the same problem. It happens because of this line inside the runnable:
fullPlayer_currentTime.setText(MusicPlayback.getTime(MusicPlayback.mediaPlayer.getCurrentPosition()));
I found the answer here: https://stackoverflow.com/a/13841982/10334697.
You have to set fixed size for your TextView.
I think its because of focus. Please set your textview like this
<TextView
android:id="#+id/textView_full_player_song"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/imageView_full_player_album_art"
android:layout_alignStart="#+id/imageView_full_player_album_art"
android:layout_below="#+id/imageView_full_player_album_art"
android:layout_marginTop="12dp"
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit ="marquee_forever"
android:focusable="true"
android:focusableInTouchMode="true"
android:scrollHorizontally="true"
android:text="Song Name"
android:textAlignment="center"
android:textColor="#color/defaultTextColor"
android:textSize="18sp" />
add this your TextView,
android:focusable="true"
android:focusableInTouchMode="true"
I inherited some big project with a lot of legacy code and now I'm facing some weird stuff..
I need to make this screen have recyclerview with grid layout manager, 2 columns. This is what I get. Is there a way to center those icons in the middle of the screen? I tried with gravity, but nothing works. Maybe there is some thing inside all that legacy code that is making problem or this is just recyclerView's issue?
This is the item's layout (terrible, don't ask..)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_view_controller_item_background"
android:orientation="vertical">
<TextView
android:id="#+id/textViewSceneKK"
android:layout_width="match_parent"
android:layout_height="#dimen/room_button_height"
android:layout_gravity="center"
android:layout_marginLeft="#dimen/row_filter_text_margin_left"
android:layout_marginRight="#dimen/row_filter_text_margin_left"
android:gravity="center"
android:shadowDx="-1"
android:shadowDy="-1"
android:shadowRadius="1"
android:textSize="#dimen/row_scene_kk_text_size" />
<TextView
android:id="#+id/textViewSceneName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/row_filter_text_margin_bottom"
android:layout_marginLeft="#dimen/row_filter_text_margin_left"
android:layout_marginRight="#dimen/row_filter_text_margin_left"
android:layout_marginTop="#dimen/row_filter_text_margin_top"
android:clickable="false"
android:gravity="center"
android:longClickable="false"
android:textColor="#color/main_text_color"
android:textSize="#dimen/row_browser_right_name_text_size" />
</LinearLayout>
<!--<View-->
<!--android:id="#+id/filterView"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:clickable="false"-->
<!--android:longClickable="false" />-->
<View
android:id="#+id/filterViewClick"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:focusable="false"
android:focusableInTouchMode="false" />
And fragment't layout:
<customview.CustomRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
And the code:
customRecyclerView.setHasFixedSize(false);
customRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
customRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
R.drawable.line_separator_empty, DividerItemDecoration.VERTICAL_LIST));
customRecyclerView.setAdapter(adapter);
CustomRecyclerView.java
public class CustomRecyclerView extends RecyclerView {
private boolean enableScroll = true;
public CustomRecyclerView(Context context) {
super(context);
}
public CustomRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public boolean isEnableScroll() {
return enableScroll;
}
public void setEnableScroll(boolean enableScroll) {
this.enableScroll = enableScroll;
}
#Override
public int computeVerticalScrollRange() {
return super.computeVerticalScrollRange();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (enableScroll) {
return super.onInterceptTouchEvent(e);
}
return false;
}
}
You have to use layout gravity to make it center & need to change match-parent to wrap_content, also you have to assign layout gravity runtime. try this code:
Adapter item layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:id="#+id/top_header_rl"
android:background="#color/app_header_color"
android:orientation="vertical">
<TextView
android:id="#+id/textViewSceneKK"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center"
android:shadowDx="-1"
android:shadowDy="-1"
android:shadowRadius="1"
android:text="Heder name"
android:textSize="26sp" />
<TextView
android:id="#+id/textViewSceneName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="false"
android:gravity="center"
android:text="Footer name"
android:longClickable="false"
android:textSize="25sp" />
</LinearLayout>
<!--<View-->
<!--android:id="#+id/filterView"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:clickable="false"-->
<!--android:longClickable="false" />-->
<View
android:id="#+id/filterViewClick"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:focusable="false"
android:focusableInTouchMode="false" />
</FrameLayout>
Adapter Code:
public class CenterGridView extends RecyclerView.Adapter<CenterGridView.CenterGridViewViewHolder> {
private Context context;
public CenterGridView(Context context){
this.context =context;
}
#Override
public CenterGridViewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CenterGridViewViewHolder(LayoutInflater.from(context).inflate(R.layout.new_tiem,parent,false));
}
#Override
public void onBindViewHolder(CenterGridViewViewHolder holder, int position) {
if(position%2==0){
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.RIGHT;
holder.top_header_rl.setLayoutParams(params);
}else{
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.LEFT;
holder.top_header_rl.setLayoutParams(params);
}
}
#Override
public int getItemCount() {
return 20;
}
class CenterGridViewViewHolder extends RecyclerView.ViewHolder{
private LinearLayout top_header_rl;
public CenterGridViewViewHolder(View itemView) {
super(itemView);
top_header_rl = (LinearLayout)itemView.findViewById(R.id.top_header_rl);
}
}
}
Main Activity layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.demostudies.CustomRecyclerView
android:id="#+id/tests"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></com.demostudies.CustomRecyclerView>
</LinearLayout>
// Set Adapter
CustomRecyclerView customRecyclerView = (CustomRecyclerView)findViewById(R.id.tests);
customRecyclerView.setHasFixedSize(false);
customRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
customRecyclerView.setAdapter(new CenterGridView(this));
try this:
it's working for me
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
>
</androidx.recyclerview.widget.RecyclerView>