Android AutoResizeTextView - Vertical Gravity off after resize - android

I'm using the AutoResizeTextView class found here. Auto Scale TextView Text to Fit within Bounds and it works great. However, I have the textview in a RelativeLayout and I have the layout_centerVertical property on the TextView set to true. Works great, unless the TextView doesn't fit and resizes itself. Then the text is no longer vertically centered within the RelativeLayout.
I'm guessing this is because the vertical alignment is performed BEFORE the TextView does its resizing.
How can I fix this? Is there a way to re-trigger the gravity alignment of the View after the text is resized?
Example layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<com.mypackage.android.AutoResizeTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Text Here"
android:maxLines="1"
android:ellipsize="end" />
</RelativeLayout>

Try to also trigger resizeText() in
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// trigger here
}
//This is called during layout when the size of this view has changed
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// trigger here
}

Related

How to increase layout_marginBottom by a number of pixels?

In a game I display a custom View and a FAB in a FrameLayout:
<?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="match_parent">
<de.slova.GameView
android:id="#+id/gameView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:src="#drawable/play_white" />
</FrameLayout>
However the FAB is shown too low and obscures the light blue bar at the bottom:
I need to increase the layout_marginBottom by the height of the light blue bar (indicated by the red arrows at the above screenshot), so that the FAB is moved up.
I do know the height of the bar in pixels (the content of my custom View is scaled by a Matrix) and I think I know the right place for this action (the onSizeChanged method in my custom View) - but my difficulty is getting ahold of the FAB's layout_marginBottom value.
How to access and change it please? I have tried:
#Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w, h, oldW, oldH);
int h = mBar.getHeight();
ViewGroup.LayoutParams params = mFab.getLayoutParams();
// how to add h to layout_marginBottom here?
mFab.setLayoutParams(params);
}
By the way I do have two methods to translate between dp and px if needed here:
public static float px2sp(Context context, float px) {
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
return px / scaledDensity;
}
public static float sp2px(Context context, float sp) {
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
return sp * scaledDensity;
}
Margin property is part of FrameLayout.LayoutParams Class, so you have to cast it to FrameLayout.LayoutParams
FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) fab.getLayoutParams();
param.bottomMargin = mBar.getHeight();
fab.setLayoutParams(param);

How to create a square layout and set it center horizontally

I want to customize a layout and make it into a square. In xml, I set the its layout_width and layout_height into 'match_parent'. And then in its onMeasure() method, I get the values of its height and width and set the shortest of them as the value of each side of square. The code is kind of like this:
<SquaredRelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
/>
public class SquaredRelativeLayout extends RelativeLayout {
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(width > height) {
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
}
Now here is my problem: I need to set this layout center horizontally of its parent. But every time when width > height, the layout will be aligned to left of its parent. Does any one how to solve this?
Use android:gravity="center" in your SquaredRelativeLayout's parent
or
use android:layout_centerInParent="true" in your SquaredRelativeLayout (instead of android:layout_centerHorizontal="true")
Use android:gravity="center" in your parent layout.

How to scroll and zoom the canvas content in android?

I have custom view,When loading this view I am drawing bitmap into canvas this bitmap drawn based on pdf pages length and size.And I am providing 2 buttons to user for drawing paths and drawing text on canvas.
For adding this View into my parent in two ways :
1 . Creating child layout(LinearLayout or RelativeLayout) inside parent layout and programatically adding Scroller in CustomView and adding custom view into childLayout.
xml Layout :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/custom_pdf_viewer_parent_relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/custom_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
/RelativeLayout>
2. Creating child layout (ScrollView inside Horizontal Scrollview) inside Parent layout and adding custom view into childLayout(ScrollView).
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.pakagename.CustomHorizontalScrillView
android:id="#+id/pages_horizontal_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/top_buttons_layout"
android:fillViewport="true" >
<com.pakagename.CustomVerticalScrollView
android:id="#+id/pages_vertical_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true" />
</com.cudrivepdfeditor.CustomHorizontalScrillView>
</RelativeLayout>
And for adding scroll into canvas I am using onMeasure(int widthMeasureSpec, int heightMeasureSpec).
In first case :
But this onMeasure is not working in first case. Because custom view is added into LinearLayout.But by programatically I am adding scroller into custom view.I don't know why onMeasure is not working.But in debugging mode widthMeasureSpec,heightMeasureSpec are not null and not 0 those have different values what exactly file have.
In second case :
In this case I am adding custom view into my verticalscrollview this verticalscrollview placed in horizantalscrollview.In this case onMeasure() method calls multiple times and it's adding scroll into customview and canvas.Canvas content also scrolls when I am scrolling.
But In my case I have zooming functionality also.When I click on zoom++ button canvas is not zooming and onMeasure() also not giving proper width and height.
in my zoom++() I called measure(requiredWidth, requiredHeight) method.
How I can scroll and zoom canvas content?Any one have any idea please help me.I stuck in this functionality from very long time.
Edit#1 :
#Override
public void onDraw(Canvas canvas) {
drawPages(canvas); // This drawPages(canvas) method draw a pages on canvas
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.width = w;
this.height = h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap); // Here I am creating new bitmap on canvas and I am drawing paths and text on this canvas.
}
Here my problem was when I am drawing paths on canvas of onDraw() it's draw a paths but when I touch up that paths are rest.And if I draw a path on mCanvas it's drawing paths and it's not resetting.But how I can scroll this mCanvas with onDraw() canvas.

Android Impossibile fill Layout height with custom view

I created a custom View, and I put this on a LinearLayout.
Problem is that I cannot fill completely the height of the layout, the size of the custom View is always squared, width = height.
Here is my layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:layout_weight="0">
<it.inav.graphics.MapView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
</LinearLayout>
The only way it seems to work is using a RelativeLayout and "strecth" the view using both
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
but still, if I try to get the size height, it returns the same length of before.
The problem was in the definition of the View, and not in the XML.
I have done copy-paste of this piece of code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d, d);
}
And, naturally, it sets the size of the View as a square with the length of the minor.
This is the correct code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
}

Making GridView items square

I would like the items of my GridView to be square. There are 2 columns and the items width is fill_parent (e.g. they take as much horizontal space as possible. The items are custom views.
How do I make the items height to be equal to their variable width?
There is a simpler solution when GridView columns are stretched. Just override the onMeasure of the GridView item layout with...
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
Or if you want to extend a View just do something really simple like:
public class SquareImageView extends ImageView
{
public SquareImageView(final Context context)
{
super(context);
}
public SquareImageView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
}
public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
setMeasuredDimension(width, width);
}
#Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh)
{
super.onSizeChanged(w, w, oldw, oldh);
}
}
It's worth noting that super.onMeasure() is not needed. onMeasured requirement is that you must call setMeasuredDimension.
I'm not sure this is possible with the current widgets. Your best bet might be to put your custom view in a custom "SquareView". This view could just contain 1 child view, and force the height to equal the width when its onLayout method is called.
I never tried to do something like that, but I think it shouldn't be too difficult. An alternative (and maybe slightly easier) solution might be to subclass your custom view's root layout (like, if it's a LinearLayout, make a SquareLinearLayout), and use that as a container instead.
edit : Here's a basic implementation which seems to work for me :
package com.mantano.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class SquareView extends ViewGroup {
public SquareView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onLayout(boolean changed, int l, int u, int r, int d) {
getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = getChildAt(0);
child.measure(widthMeasureSpec, widthMeasureSpec);
int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec);
child.measure(width, width); // 2nd pass with the correct size
setMeasuredDimension(width, width);
}
}
It's designed to have a unique child, but I ignored all of the checks for the sake of simplicity. The basic idea is to measure the child with the width/height parameters set by the GridView (in my case, it uses numColumns=4 to calculate the width), and then do a second pass with the final dimensions, with height=width...
The layout is just a plain layout, which layouts the unique child at (0, 0) with the desired dimensions (right-left, down-up).
And here's the XML used for the GridView items :
<?xml version="1.0" encoding="utf-8"?>
<com.mantano.widget.SquareView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<LinearLayout android:id="#+id/item" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal"
android:gravity="center">
<TextView android:id="#+id/text" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Hello world" />
</LinearLayout>
</com.mantano.widget.SquareView>
I used a LinearLayout inside the SquareView in order to have it manage all the gravity possibilities, margins, etc.
I'm not sure how well (or bad) this widget would react to orientation and dimension changes, but it seems to work correctly.
It ends up being fairly easy to get the grid item square.
In your "GetView" method of your grid adapter, just do:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
GridView grid = (GridView)parent;
int size = grid.getRequestedColumnWidth();
TextView text = new TextView(getContext());
text.setLayoutParams(new GridView.LayoutParams(size, size));
// Whatever else you need to set on your view
return text;
}
I don`t know if it is the best way, but I accomplish that making my custom view to override onSizeChanged that way:
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (getLayoutParams() != null && w != h) {
getLayoutParams().height = w;
setLayoutParams(getLayoutParams());
}
}
I use this custom view inside a LinearLayout and a GridView and in both it is showing square!
Try
<GridView
...
android:stretchMode="columnWidth" />
You can also play with other modes
This worked for me!
If you are like me and you can't use getRequestedColumnWidth() because your minSdk is lower than 16, I suggest this option.
in your fragment:
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
int size = dm.widthPixels / nbColumns;
CustomAdapter adapter = new CustomAdapter(list, size, getActivity());
in your adapter (in getView(int position, View convertView, ViewGroup parent))
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
fragment.xml:
<GridView
android:id="#+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="3dp"
android:verticalSpacing="3dp"
android:numColumns="4"
android:stretchMode="columnWidth" />
custom_item.xml: (for example)
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
Hope it will help someone!
if you set a static number of columns in the xml then you can take the width of the view and divide it by the number of columns.
if you are using auto_fit then it's going to be a bit tricky to get the column count ( there is no getColumnCount() method ), btw this question should help you somehow.
this is the code I'm using into the getView(...) method of the adapter with a fixed number of columns:
item_side = mFragment.holder.grid.getWidth() / N_COL;
v.getLayoutParams().height = item_side;
v.getLayoutParams().width = item_side;
This is what I am doing to show square cells in a GridView. I am not sure if you want square cells or something else.
GridView grid = new GridView( this );
grid.setColumnWidth( UIScheme.cellSize );
grid.setVerticalSpacing( UIScheme.gap );
grid.setStretchMode( GridView.STRETCH_COLUMN_WIDTH );
grid.setNumColumns( GridView.AUTO_FIT );
And then the view which I am creating for each cell I have to do the following to it:
cell.setLayoutParams( new GridView.LayoutParams(iconSize, iconSize) );
Based on SteveBorkman's answer, which is API 16+:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
GridView grid = (GridView)parent;
int size = grid.getColumnWidth();
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.your_item, null);
convertView.setLayoutParams(new GridView.LayoutParams(size, size));
}
//Modify your convertView here
return convertView;
}
Along the lines of #Gregory's answer, I had to wrap my image in a LinearLayout in order to keep GridView from manipulating its dimensions from square. Note that the outer LinearLayout should be set to have the dimension of the image, and the width of the GridView column should be the width of the image PLUS any margin. For example:
<!-- LinearLayout wrapper necessary to wrap image button in order to keep square;
otherwise, the grid view distorts it into rectangle.
also, margin top and right allows the indicator overlay to extend top and right.
NB: grid width is set in filter_icon_page.xml, and must correspond to size + margin
-->
<LinearLayout
android:id="#+id/sport_icon_lay"
android:layout_width="60dp"
android:layout_height="60dp"
android:orientation="vertical"
android:layout_marginRight="6dp"
android:layout_marginTop="6dp"
>
<ImageButton
android:id="#+id/sport_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:maxHeight="60dp"
android:maxWidth="60dp"
android:scaleType="fitCenter"
/>
</LinearLayout>
and the GridView like:
<GridView
android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:columnWidth="66dp"
android:numColumns="auto_fit"
android:verticalSpacing="25dp"
android:horizontalSpacing="24dp"
android:stretchMode="spacingWidth"
/>
In your activity
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
valX = displaymetrics.widthPixels/columns_number;
in the CustomAdapter of the GridView
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, YourActivity.valX));

Categories

Resources