Android: how to configure sizing of a custom layout - android

I've been trying to create a custom horizontal layout with the goal to have a TextView to the left of an ImageView, containing a icon which depicts a certain status. The ImageView is to kept in a square dimension, with it's height and width equal to the height of the text in the TextView. Issues continue to persist, however, such as the text height not being set as specified in the layout xml file and an unknown padding existing after the ImageView. These problem can be seen in this image, with the red indicating the unknown padding and the blue indicating the text size inconsistency where both where set to 12sp. The font sizing and padding issues need to be fixed so the layout can be properly added to a grid layout, which will contain a grid of these custom layouts.
StatusIcon.java
//This is part of the java class that extends ImageView to resize the Icon
#Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
int measuredHeight = getMeasuredHeight();
setMeasuredDimension(measuredHeight, measuredHeight);
}
StatusIndicator.java
//This is the java class for the custom layout.
public class StatusIndicator extends LinearLayout {
private TextView label;
private StatusIcon statusLed;
private CharSequence labelText;
private float labelTextSize;
public enum Status {
GOOD,
WARNING,
CRITICAL
}
/*
* Removed the basic required class constructors to save space.
*/
private void getAttributes(Context context, AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StatusIndicator);
labelText = typedArray.getString(R.styleable.StatusIndicator_label);
labelTextSize = typedArray.getDimensionPixelSize(R.styleable.StatusIndicator_labelSize, 0);
typedArray.recycle();
}
private void initializeViews(Context context){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.view_status_indicator, this);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
//Setup UI elements in layout
label = (TextView) findViewById(R.id.textView_statusIndicatorLabel);
statusLed = (StatusIcon) findViewById(R.id.imageView_statusIndicatorLed);
label.setText(labelText);
if(labelTextSize > 0){
label.setTextSize(TypedValue.COMPLEX_UNIT_SP, labelTextSize);
}
}
public void setStatus(StatusIndicator.Status status){
switch (status){
case GOOD:
statusLed.setImageResource(R.mipmap.ic_status_panel_good);
break;
case WARNING:
statusLed.setImageResource(R.mipmap.ic_status_panel_warning);
break;
case CRITICAL:
statusLed.setImageResource(R.mipmap.ic_status_panel_critical);
break;
}
}
}
view_status_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<merge 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"
tools:parentTag="LinearLayout"
tools:orientation="horizontal">
<TextView
android:id="#+id/textView_statusIndicatorLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|start"
android:layout_marginEnd="2dp"
android:text="#string/default_title"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textSize="12sp"/>
<com.css_design.android_quickbridge.ui.home.status_panel.StatusIcon
android:id="#+id/imageView_statusIndicatorLed"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center_vertical|end"
app:srcCompat="#mipmap/ic_status_panel_critical"/>
</merge>

I would solve this problem by using ConstraintLayout instead of creating a custom view implementation.
ConstraintLayout allows you to specify an aspect ratio for its children, which takes care of wanting to make sure your ImageView is always exactly square. ConstraintLayout also allows you to specify height or width based on sibling views (by combining a dimension of 0dp with top and bottom (or left and right) constraints).
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:layout_height="wrap_content"
android:background="#ccf">
<ImageView
android:id="#+id/image"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="#drawable/circle"
app:layout_constraintTop_toTopOf="#+id/text"
app:layout_constraintLeft_toRightOf="#+id/text"
app:layout_constraintBottom_toBottomOf="#+id/text"
app:layout_constraintDimensionRatio="1"/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:text="hello world"/>
</android.support.constraint.ConstraintLayout>
(Background color added to the ConstraintLayout to show that it's not any larger than its contents).

Related

Dynamically adding a View to a LinearLayout with height of wrap_content doesn't display anything

I'm trying to dynamically add a view to a LinearLayout using the wrap_content height. However it doesn't work unless I add a defined dp height such as 300dp. Why can't I programmatically add the View and having the Parent LinearLayout wrap the contents?
The view I'm trying to add:
public class ImageCanvas extends View {
private static final String TAG = "ImageCanvas";
private Bitmap icon;
public ImageCanvas(Context context) {
super(context);
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.piggy);
if(drawable != null){
icon = ((BitmapDrawable) drawable).getBitmap();
}
Log.d(TAG, "ImageCanvas: " + icon);
}
public ImageCanvas(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public ImageCanvas(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(icon, 0, 0, null);
}
}
The LinearLayout I'm trying to add the above view to:
<LinearLayout
android:id="#+id/drawingPad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#+id/btn_create_image"
app:layout_constraintBottom_toBottomOf="parent"
android:paddingBottom="32dp"
android:orientation="vertical"
android:paddingTop="32dp"/>
Creating the view programmatically and adding it:
LinearLayout drawingPad = findViewById(R.id.drawingPad);
ImageCanvas imageCanvas = new ImageCanvas(context);
drawingPad.addView(imageCanvas);
It works when I set the XML LinearLayout to a defined height like 200dp but it doesn't work with wrap_content, how can I get it to do so with wrap_content?
_________________________________________________________
Update 1:
I simplified everything down to the XML layout and the issue turned out to be a Parent NestedScrollView.
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/btn_create_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="Create image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/drawingPad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="32dp"
android:paddingBottom="32dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btn_create_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
This is the entire layout. When you add a NestedScrollView and you try to add a view programmatically, the Bitmap WILL NOT draw on screen. When you remove the NestedScrollView the Bitmap will appear. If anyone knows how to do it with a NestedScrollView please share!
You need to provide measurements of ImageCanvas with an onMeasure() override:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(icon.getWidth(),icon.getHeight());
}
See Custom View Components.
When you explicitly supply a height, that height is set in the custom component. With wrap content, the height gets set to zero since it is neither specified nor explicitly measured. The above code will provide the correct measurements.
(icon.getHeight() is what you really need and corresponds to wrap_content. You may need a different value for icon.getWidth() depending upon your design.)
Not sure why a NestedScrollView has any effect, but the code above will help.
The problem may lay with your constraint layout.
for constraint layout >= 1.1
app:layout_constrainedHeight=”true"
android:layout_height="wrap_content"
for constraint layout <1.1
android:layout_height="wrap_content"
app:layout_constraintHeight_default="wrap"
This always gets me maybe it got you.
(edit) this needs to be in the child of the constraint layout not the constraint layout itself, ie LinearLayout.

Custom Square Layout not working as expected

I stumbled across this problem when working with custom Square Layout : by extending the Layout and overriding its onMeasure() method to make the dimensions = smaller of the two (height or width).
Following is the custom Layout code :
public class CustomSquareLayout extends RelativeLayout{
public CustomSquareLayout(Context context) {
super(context);
}
public CustomSquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSquareLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CustomSquareLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Width is smaller
if(widthMeasureSpec < heightMeasureSpec)
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
//Height is smaller
else
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
}
}
The custom Square Layout works fine, until in cases where the custom layout goes out of bound of the screen. What should have automatically adjusted to screen dimensions though, doesn't happen. As seen below, the CustomSquareLayout actually extends below the screen (invisible). What I expect is for the onMeasure to handle this, and give appropriate measurements. But that is not the case. Note of interest here is that even thought the CustomSquareLayout behaves weirdly, its child layouts all fall under a Square shaped layout that is always placed on the Left hand side.
<!-- XML for above image -->
<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"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:text="Below is the Square Layout"
android:gravity="center"
android:id="#+id/text"
/>
<com.app.application.CustomSquareLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/text"
android:background="#color/colorAccent" #PINK
android:layout_centerInParent="true"
android:id="#+id/square"
android:padding="16dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" #Note this
android:background="#color/colorPrimaryDark" #BLUE
>
</RelativeLayout>
</com.app.application.CustomSquareLayout>
</RelativeLayout>
Normal case : (Textview is in Top)
Following are few links I referenced:
Custom Square LinearLayout. How?
Simple way to do dynamic but square layout
Hope to find a solution to this, using onMeasure or any other function when extending the layout (so that even if some extends the Custom Layout, the Square property remains)
Edit 1 : For further clarification, the expected result for 1st case is shown
Edit 2 : I gave a preference to onMeasure() or such functions as the need is for the layout specs (dimensions) to be decided earlier (before rendering). Otherwise changing the dimensions after the component loads is simple, but is not requested.
You can force a square view by checking for "squareness" after layout. Add the following code to onCreate().
final View squareView = findViewById(R.id.square);
squareView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
squareView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
if (squareView.getWidth() != squareView.getHeight()) {
int squareSize = Math.min(squareView.getWidth(), squareView.getHeight());
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) squareView.getLayoutParams();
lp.width = squareSize;
lp.height = squareSize;
squareView.requestLayout();
}
}
});
This will force a remeasurement and layout of the square view with a specified size that replaces MATCH_PARENT. Not incredibly elegant, but it works.
You can also add a PreDraw listener to your custom view.
onPreDraw
boolean onPreDraw ()
Callback method to be invoked when the view tree is about to be drawn. At this point, all views in the tree have been measured and given a frame. Clients can use this to adjust their scroll bounds or even to request a new layout before drawing occurs.
Return true to proceed with the current drawing pass, or false to cancel.
Add a call to an initialization method in each constructor in the custom view:
private void init() {
this.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
if (getWidth() != getHeight()) {
int squareSize = Math.min(getWidth(), getHeight());
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
lp.width = squareSize;
lp.height = squareSize;
requestLayout();
return false;
}
return true;
}
});
}
The XML can look like the following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:gravity="center"
android:text="Below is the Square Layout" />
<com.example.squareview.CustomSquareLayout
android:id="#+id/square"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/text"
android:background="#color/colorAccent"
android:padding="16dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#color/colorPrimaryDark" />
</com.example.squareview.CustomSquareLayout>
</RelativeLayout>
There is a difference between the view's measured width and the view's width (same for height). onMeasure is only setting the view's measured dimensions. There is still a different part of the drawing process that constrains the view's actual dimensions so that they don't go outside the parent.
If I add this code:
final View square = findViewById(R.id.square);
square.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
System.out.println("measured width: " + square.getMeasuredWidth());
System.out.println("measured height: " + square.getMeasuredHeight());
System.out.println("actual width: " + square.getWidth());
System.out.println("actual height: " + square.getHeight());
}
});
I see this in the logs:
09-05 10:19:25.768 4591 4591 I System.out: measured width: 579
09-05 10:19:25.768 4591 4591 I System.out: measured height: 579
09-05 10:19:25.768 4591 4591 I System.out: actual width: 768
09-05 10:19:25.768 4591 4591 I System.out: actual height: 579
How to solve it by creating a custom view? I don't know; I never learned. But I do know how to solve it without having to write any Java code at all: use ConstraintLayout.
ConstraintLayout supports the idea that children should be able to set their dimensions using an aspect ratio, so you can simply use a ratio of 1 and get a square child. Here's my updated layout (the key piece is the app:layout_constraintDimensionRatio attr):
<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="match_parent">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:gravity="center"
android:text="Below is the Square Layout"
app:layout_constraintTop_toTopOf="parent"/>
<RelativeLayout
android:id="#+id/square"
android:layout_width="match_parent"
android:layout_height="0dp"
android:padding="16dp"
android:background="#color/colorAccent"
app:layout_constraintTop_toBottomOf="#+id/text"
app:layout_constraintDimensionRatio="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#color/colorPrimaryDark">
</RelativeLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
And screenshots:
You cannot compare the two measure specs, as they are not simply a size. You can see a very good explanation in this answer. This answer is for a custom view, but measure specs are the same. You need to get the mode and the size to compute final sizes, and compare the end results for both dimensions.
In the second example you shared, the right question is this one (third answer). Is written for Xamarin in C#, but is easy to understand.
The case that is failing for you is because you're finding an AT_MOST mode (when the view is hitting the bottom of the screen), that's why comparisons are failing in this case.
That should be the final method (can contain typos, I have been unable to test it:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width, height;
switch (widthMode) {
case MeasureSpec.EXACTLY:
width = widthSize;
break;
case MeasureSpec.AT_MOST:
width = Math.min(widthSize, heightSize);
break;
default:
width = 100;
break;
}
switch (heightMode) {
case MeasureSpec.EXACTLY:
height = heightSize;
break;
case MeasureSpec.AT_MOST:
height = Math.min(widthSize, heightSize);
break;
default:
height = 100;
break;
}
var size = Math.min(width, height);
var newMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
super.onMeasure(newMeasureSpec, newMeasureSpec);
}
I expect the end result to be roughly like this (maybe centered, but this dimensions):
Notice that this is a made up image done with Gimp.
try this. You can use on measure method to make a custom view. Check the link below for more details.
http://codecops.blogspot.in/2017/06/how-to-make-responsive-imageview-in.html

Custom LinearLayout - childs not visible

I build customView extending LinearLayout and having simple 3 childrens(2 TextView and ImageView). I create this view dynamically in code and adding it to parent LinearLayout. This view has background, so I can easily spot on the screen, that it is inflated correctly in its place, but any of child is not visible. I checked LayoutInspector and it shows that everything is setted correctly(text values to TextViews and picture to ImageView), but somehow when I try to locate them on inspector they are shown as little dot over my customView:
My CustomView is called DayTileView and this is square with gray background. As you can see on inspector on the left childrens are filled with content. Layout of View:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<merge>
<TextView
android:id="#+id/day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#android:color/white"
/>
<TextView
android:id="#+id/dayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#android:color/white"
/>
<ImageView
android:id="#+id/padlock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_padlock"
/>
</merge>
</layout>
And its code:
public class DayTileView extends LinearLayout {
private DayTileBinding mBinding;
public DayTileView(Context context) {
super(context);
init();
}
public DayTileView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public DayTileView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mBinding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.day_tile, this, true);
setOrientation(VERTICAL);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
setMeasuredDimension(width, width);
}
public void setDay(int day, int month, int year) {
DateTime settedDay = new DateTime().withYear(year).withMonthOfYear(month).withDayOfMonth(day);
mBinding.day.setText(String.valueOf(day));
String dayName = settedDay.dayOfWeek().getAsText();
mBinding.dayName.setText(dayName);
boolean isWeekend = settedDay.dayOfWeek().get() == 6 || settedDay.dayOfWeek().get() == 7;
setBackgroundColor(ContextCompat.getColor(getContext(), isWeekend ? R.color.weekend_bg : R.color.weekday_bg));
}
}
Its use in another CustomView which is also LinearLayout but wiht horizontal orientation (PlannedDayView on inspector):
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<merge>
<*.customViews.DayTileView
android:id="#+id/dayTile"
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/container"
android:orientation="vertical"
android:layout_weight="1.2"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
</merge>
</layout>
Has anyone any idea what could be casuing this (childs out of view)? When I replace merge for LinearLayout with vertical orientation and same background everything in Design mode of layout is visible correctly, so it should work.
EDIT:
I found out, that if I set during View initalization Padding Top to 10px then dot is moving down. So it looks like from some reasons Android didn't made to inflate correctly TextViews and ImageView
I found out what was the problem:
I overrided onMeasure and didn't measure child Views. Earlier I was using such code to make square View not square ViewGroup.
Corrected code:
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
setMeasuredDimension(width, width);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
After setting correct width and height for View I must measure whole view with new MeasureSpec

Android - How to set margin to custom LinearLayouts in GridLayout?

I have problems with setting margin to a custom made linear layout class that I use multiple times in a GridLayout. The Gridlayout is placed in a fragment.
This is the code of fragment_grid.xml:
<FrameLayout 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"
tools:context="app_a_tize.expressme.Fragment.GridFragment"
android:layout_gravity="center">
<GridLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/orange"
android:layout_margin="5dp"
android:id="#+id/gridlayout_grid"></GridLayout>
</FrameLayout>
This is the code of the GridFragment.java:
public class GridFragment extends Fragment {
public GridFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_grid, container, false);
}
#Override
public void onStart() {
super.onStart();
GridLayout grid = (GridLayout) getView().findViewById(R.id.gridlayout_grid);
grid.setRowCount(3);
int tileHeight = (CategoryTileActivity.gridContentHeight -3 * 10) / 3;
int amountofColumns = (int) CategoryTileActivity.gridContentWidth / tileHeight;
grid.setColumnCount(amountofColumns);
grid.setMinimumWidth((amountofColumns * tileHeight) + (5 * 20 ));
for (int i = 0; i < 3 * amountofColumns; i++) {
//fill the grid with the custom LinearLayout:
grid.addView(new TileClass(getActivity(), tileHeight, tileHeight, "ToBeImplemented", "Button"));
}
}
}
This is the code of the custom LinearLayout:
public class TileClass extends LinearLayout {
public TileClass(Context context, int height, int width, String image, String text) {
super(context);
this.setBackgroundResource(R.drawable.tile_button); //creates rounded layouts
this.setMinimumHeight(height);
this.setMinimumWidth(width);
this.setOrientation(LinearLayout.VERTICAL);
ImageView tileImage = new ImageView(context);
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.tilephoto);
Bitmap bMapScaled = Bitmap.createScaledBitmap(bMap, 100, 100, true);
tileImage.setImageBitmap(bMapScaled);
tileImage.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TextView tileText = new TextView(context);
tileText.setText(text);
tileText.setTextColor(Color.WHITE);
tileText.setGravity(Gravity.CENTER);
addView(tileImage);
addView(tileText);
}
}
When I run the Activity, I get this as result:
The code I showed above is responsible for the orange area in the middle. What I need: the blue "buttons"/LinearLayouts, in the orange area in the middle, to have a margin of 5dp. So the rest of the orange space is be taken by the custom LinearLayouts.
I don't know how to fix that, I tried a lot of options but they don't seem to work out for me.. Everything from MarginLayoutParams to params.setMargins(5,5,5,5); On almost every layout in my code.
I use Android Studio 2.1.2, supporting minimum of API 15.
Every help is appreciated!
For your imagination, this must be the end result, I need the margin like this:
You have to make custom view of gridview item as below:-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/categoryHeight"
android:layout_marginLeft="#dimen/margin_5dp"
android:layout_marginRight="#dimen/margin_5dp"
android:layout_marginTop="#dimen/margin_7dp"
android:background="#drawable/rounded_bg"
>
<ImageView
android:id="#+id/llRowItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scaleType="fitXY"
android:gravity="bottom"/>
<TextView
android:id="#+id/item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/black_light"
android:padding="#dimen/margin_5dp"
android:layout_gravity="bottom"
android:singleLine="true"
android:textColor="#color/white"
android:textSize="#dimen/font_size_16sp" />
</FrameLayout>
and inside adapter set color of text view, background, text or image of imageview whatever you want to set.

How to find layout_marginTop

I have an XML file with the following attritubes:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/al_cs_layout1"
android:gravity="center_vertical">
<ImageView android:id="#+id/cs_track"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/fader_background5"
android:layout_marginLeft="0dp"
android:layout_marginTop="20dp" >
</ImageView>
...
and here is my java code:
public void initialize(Context context)
{
Log.d("initialize (MySeekBar)","initialize");
setWillNotDraw(false);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view1 = inflater.inflate(R.layout.custom_seekbar, this);
layout1 = (RelativeLayout)view1.findViewById(R.id.al_cs_layout1);
track = (ImageView)layout1.findViewById(R.id.cs_track);
thumb = (ImageView)layout1.findViewById(R.id.cs_thumb);
...
I am working on a custom seekbar which determines the top by using a variable marginTop = 20; however this was oringally made on a phone much older by a different programmer. The 20 suppose to represent the margin top defined in the XML however it is using dp and not pixels. how can I find the marginTop attribute of R.id.cs_track? It works great on the old phone but on any phone does doesn't have the same screen size of dp it will create an undesired offset.
Use MarginLayoutParams to get value in pixels:
track = (ImageView)layout1.findViewById(R.id.cs_track);
MarginLayoutParams params = (MarginLayoutParams)track.getLayoutParams();
int marginTopPixelSize = params.topMargin;

Categories

Resources