How Can I create a Circular CardView in Android? - android

i'm trying to create a circular CardView. But I don't know how to do it. Is there any attribute with which I can get a Circular CardView?.
The XML code is the following:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_outer"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"
card_view:cardBackgroundColor="#android:color/transparent"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="3dp" >
</android.support.v7.widget.CardView>

Just use the shapeAppearanceOverlay attribute:
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp"
android:layout_height="100dp"
app:cardBackgroundColor="#color/colorPrimaryLight"
app:shapeAppearanceOverlay="#style/circle"
/>
with:
<style name="circle">
<item name="cornerSize">50%</item>
</style>

<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="10dp"
app:cardCornerRadius="100dp"/>
May be changing app:cardCornerRadius to half of the width and height.
OR
May be Custom CardView
public class CircularCardView extends CardView {
public CircularCardView(#NonNull Context context) {
super(context);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
setRadius(width/2);
}
}
XML
<com.yourpackage.name.CircularCardView
android:layout_width="50dp"
android:layout_height="100dp"
android:layout_margin="10dp"
app:cardElevation="10dp"
/>

I wanted to have a circular image So did something like this
<androidx.cardview.widget.CardView
android:id="#+id/roundCardView"
android:layout_width="100dp"
android:layout_height="100dp"
android:elevation="0dp"
app:cardCornerRadius="10dp"
app:layout_constraintTop_toTopOf="#id/userName"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="20dp">
<ImageView
android:id="#+id/profilePic"
android:layout_width="100dp"
android:layout_height="100dp" />
</androidx.cardview.widget.CardView>

Its better if you migrate to androidx but you can use this code add shape to your card view
<app:android.support.v7.widget.CardView
android:layout_width="150dp"
android:layout_height="148dp"
android:elevation="12dp"
app:cardCornerRadius="75dp"
android:layout_centerHorizontal="true"
android:innerRadius="40dp"
android:shape="ring"
android:thicknessRatio="4">
</app:android.support.v7.widget.CardView>

This worked for me for all Android Versions
<androidx.cardview.widget.CardView
android:layout_width="90dp"
android:layout_height="90dp"
app:cardCornerRadius="45dp"
android:shape="ring"
app:cardElevation="5dp">

Related

How can I change the column count in android automatically based on the content of recyclerview?

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"
/>

How to center text in custom "square" TextView

I've create a custom TextView because I want:
its height to match certain constraints (top to top and bottom to bottom of another TextView)
its width matching that height so the oval shape xml set as background of the TextView shows a circle.
Here's the code of the custom View:
public class SquareTextView extends AppCompatTextView {
public static final String TAG = "SquareTextView";
int squareDim = 0;
public SquareTextView(Context context) {
super(context);
}
public SquareTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int h = this.getMeasuredHeight();
int w = this.getMeasuredWidth();
squareDim = Math.max(w, h);
setMeasuredDimension(squareDim, squareDim);
}
}
layout xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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">
<android.support.constraint.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">
<TextView
android:id="#+id/tv_registration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:text="WW-WWW"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tv_aircraft_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MMMMMMMMM"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="#+id/tv_registration"
app:layout_constraintTop_toBottomOf="#+id/tv_registration" />
<com.mydomain.SquareTextView
android:id="#+id/tv_counter"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="24dp"
android:background="#drawable/shape_circle"
android:gravity="center"
android:text="0"
android:textAlignment="center"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/tv_registration"
app:layout_constraintBottom_toTopOf="#+id/cv_ops_restrictions"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
shape_circle.xml:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<size android:width="50dp"
android:height="50dp"/>
<solid android:color="#android:color/white"/>
</shape>
Problem is that I want the text centered in the circle. Any pointers on how to achieve this or on what I'm doing wrong? at the moment it looks like this:
I'd like to recommend that you don't use a custom TextView subclass at all here. You're already working inside ConstraintLayout, which supports aspect ratios for its children. That means you can replace <com.mydomain.SquareTextView> with <TextView> and add this attribute to get a perfect square view:
app:layout_constraintDimensionRatio="1:1"

GridLayout with images going off screen

I'm trying to create a GridLayout with images. The grid has 3 columns.
I have a few problems though:
The ImageViews are going off the screen, as shown in the image below. The GridLayout isn't properly setting the width of the ImageViews to fit.
There is no space/margin between the ImageViews, even though I have set the horizontalSpacing and verticalSpacing properties for the GridLayout.
Here is my current code. What should I change to fix my two problems?
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:stretchMode="columnWidth">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
</GridLayout>
Update
Following this answer, I tried using the following layout:
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3">
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
</GridLayout>
But it comes out looking like the image below. Each ImageView takes up the entire width of the screen:
http://i.imgur.com/p8AXcKN.png
You should reduce the layout_width="130dp" because your screen isn't guaranteed to be 390dp
Change the images or you can also use Square Image View for proper sizing of your Grid Items.
Create a separate class for defining the size dynamically for your ImageView that should inherit ImageView class as shown below:
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
The setMeasuredDimension(width, width); will automatically set your height as the width.
In xml file use this class as a view in place of ImageView as shown below:
<com.packagepath.SquareImageView
android:id="#+id/Imageview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

Square buttons Screen Width and Weight Matching

I have a layout which contains only a LinearLayour with 3 buttons inside.
I would want this 3 buttons to fill the screen vertically so I used "weigth=1" but I should also want the buttons to be square, that is, that their width is equal to their height.
Any way to do it?
Here's the .xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="android.jose.se.Prueba"
android:background="#drawable/bg"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/bHet"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer1"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bGay"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer2"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bLesbi"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer3"
android:onClick="cambiarBoton"/>
</LinearLayout>
</RelativeLayout>
I had similar issue and done it using Google's Percent Relative Layout that helps you manage view aspect ratio.
You can use it like this
<android.support.percent.PercentRelativeLayout
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="match_parent">
<Button
android:layout_width="match_parent"
app:layout_aspectRatio="100%"/>
</android.support.percent.PercentFrameLayout>
The best way to do this, is to make a new Class called Square button and this class should extend Button. Then in the onMeasure of this class, simply make your heightSpec as WidthSpec.
public class SquareButton extends Button {
public SquareButton(Context context) {
super(context);
}
public SquareButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int WidthSpec, int HeightSpec){
int newWidthSpec = HeightSpec ;
super.onMeasure(newWidthSpec, HeightSpec);
}}
Now you can use this SquareButton instead of a normal Button in your xml like this. The value of android:width attribute will be ignored.
<com.example.package.SquareButton
android:height = "0dp"
android:weight = "1"
android:width = "0dp"
/>

Combining layout_weight and maxHeight

I'm quite new to Android programming and I'm stuck on an simple problem.
I have a basic homepage with some buttons and a logo. I use a LinearLayout and the layout_weight attribute to distribute all the components.
Here is my code :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="iut.project.findmeapp.MainActivity" >
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:contentDescription="#string/description_logo"
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
android:layout_margin="#dimen/img_margin"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:gravity="center"
android:layout_weight="0.5"
android:layout_margin="#dimen/tw_margin"
android:text="#string/copyright" />
</LinearLayout>
(Note : #dimen/null_height is 0dp)
My problem is that I want the image to scale with the size of the screen, but I don't want it pixelated : I have set a maximum height of 200px.
The following lines don't seem to work, because the image has no limit and totally ignores the maxHeight attribute.
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
Actually it looks like this (example image) :
It works perfectly, but when I set maxHeight to 10px for example, nothing changes.
How can I achieve this ? I highly prefer to use a LinearLayout.
Thank you in advance.
Thanks to Evripidis Drakos for pointing me in the right direction. Just need a check to only set the max height if it's actually required.
public class MaxHeightImageView extends ImageView {
public static final int MAX_HEIGHT_NOT_SET = -1;
public static final int INDEX_MAX_HEIGHT = 0;
private static final int[] STYLE_ATTRIBUTE_ARRAY = {
android.R.attr.maxHeight,
};
private int myMaxHeight;
public MaxHeightImageView(Context context) {
super(context);
init(context, null);
}
public MaxHeightImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(heightMeasureSpec);
if(MAX_HEIGHT_NOT_SET != myMaxHeight && size > myMaxHeight) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(myMaxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void init(Context context, AttributeSet attrs) {
if(context != null) {
TypedArray ta = context.obtainStyledAttributes(attrs,
STYLE_ATTRIBUTE_ARRAY);
myMaxHeight = ta.getDimensionPixelSize(INDEX_MAX_HEIGHT, 0);
} else {
myMaxHeight = MAX_HEIGHT_NOT_SET;
}
}
}
I dont think that you can combine layout_weight with maxHeight.
You could try subclassing ImageView to override the onMeasure method like so:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(200, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
if u want to set exact height for your image u should use weightSum property with weight
edit:
for fixed height do not give weight for imageview just take parent layout for imageview then add weight for that linear layout(parent layout) and for imageview give height as wrap content and maxHeight. when u use weight with height="0dp" the content will capture the whole height so it will ignore maxHeight.
try this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:weightSum="5"
tools:context="iut.project.findmeapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="#string/quantity_hint"
android:maxHeight="200px"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".5"
android:gravity="center"
android:text="copyright" />
</LinearLayout>

Categories

Resources