I'm newbie to android and have a problem with it.
I'm trying to make a customized view in android for menu.
I want it to have 4 elements which have images.
But these are invisible though I coded like below :( What can I do for it ?
I've googled it for a while and there's no reasonable solution in my case ...
Menuindicator.java
public class MenuIndicator extends FrameLayout {
private static final int MIN_WIDTH = 50;
private static final int MIN_HEIGHT = 50;
private final float ACTUAL_PIXELS = getContext().getResources().getDisplayMetrics().density;
private ImageView menuComponentAbove = null;
private ImageView menuComponentBelow = null;
private ImageView menuComponentFront = null;
private ImageView menuComponentBack = null;
public MenuIndicator(Context context) {
super(context);
init(null, 0);
}
public MenuIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public MenuIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MenuIndicator, defStyle, 0);
LayoutInflater.from(getContext()).inflate(R.layout.layout_menu_indicator, this);
menuComponentAbove = (ImageView) findViewById(R.id.menu_component_above);
menuComponentBelow = (ImageView) findViewById(R.id.menu_component_below);
menuComponentFront = (ImageView) findViewById(R.id.menu_component_front);
menuComponentBack = (ImageView) findViewById(R.id.menu_component_back);
typedArray.recycle();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = 0;
switch(widthMode) {
case MeasureSpec.UNSPECIFIED: widthSize = widthMeasureSpec; break;
case MeasureSpec.AT_MOST: widthSize = (int)(MIN_WIDTH * ACTUAL_PIXELS); break;
case MeasureSpec.EXACTLY: widthSize = MeasureSpec.getSize(widthMeasureSpec); break;
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = 0;
switch(heightMode) {
case MeasureSpec.UNSPECIFIED: heightSize = heightMeasureSpec; break;
case MeasureSpec.AT_MOST: heightSize = (int)(MIN_HEIGHT * ACTUAL_PIXELS); break;
case MeasureSpec.EXACTLY: heightSize = MeasureSpec.getSize(heightMeasureSpec); break;
}
setMeasuredDimension(widthSize, heightSize);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
menuComponentAbove.draw(canvas);
menuComponentBelow.draw(canvas);
menuComponentFront.draw(canvas);
menuComponentBack.draw(canvas);
invalidate();
}
}
layout_menu_indicator.xml
<!-- layout_menu_indicator.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:background="#171717">
<RelativeLayout
android:id="#+id/menu_indicator"
android:layout_width="#dimen/dimen_menu_indicator"
android:layout_height="#dimen/dimen_menu_indicator"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
<ImageView
android:id="#+id/menu_component_front"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_centerVertical="true"
android:antialias="true"
android:src="#drawable/menu_component" />
<ImageView
android:id="#+id/menu_component_back"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_centerVertical="true"
android:antialias="true"
android:src="#drawable/menu_component" />
<ImageView
android:id="#+id/menu_component_above"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_above="#id/menu_component_front"
android:layout_centerVertical="true"
android:antialias="true"
android:src="#drawable/menu_component" />
<ImageView
android:id="#+id/menu_component_below"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_below="#id/menu_component_front"
android:layout_centerVertical="true"
android:antialias="true"
android:src="#drawable/menu_component" />
</RelativeLayout>
<LinearLayout
android:id="#+id/command_container_horizontal"
android:layout_width="wrap_content"
android:layout_height="#dimen/dimen_menu_indicator"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/menu_indicator"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="#+id/command_container_vertical"
android:layout_width="#dimen/dimen_menu_indicator"
android:layout_height="wrap_content"
android:layout_below="#+id/menu_indicator"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:orientation="vertical">
</LinearLayout>
</RelativeLayout>
Add this:
public MenuIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(getContext()).inflate(R.layout.layout_menu_indicator, this);
menuComponentAbove = (ImageView) findViewById(R.id.menu_component_above);
menuComponentBelow = (ImageView) findViewById(R.id.menu_component_below);
menuComponentFront = (ImageView) findViewById(R.id.menu_component_front);
menuComponentBack = (ImageView) findViewById(R.id.menu_component_back);
}
And remove that code from your init() method
Related
In this below code i want to set center_horizontal as attachmentSlidingLayer view id but layout_gravity and gravity for parent and child view doesn't work correctly and by default gravity is left side
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:slidingLayer="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<io.codetail.widget.RevealFrameLayout <!-- extends from FrameLayout -->
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<com.test.libraries.SlidingLayer <!-- extends from BoundedFrameLayout-->
android:id="#+id/attachmentSlidingLayer"
android:layout_width="match_parent"
android:layout_height="210dp"
android:layout_gravity="center_horizontal"
android:elevation="5dp"
app:bounded_width="450dp"
android:foregroundGravity="center_horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:background="#drawable/sheet_shadow"
android:orientation="vertical"
app:bounded_width="450dp">
</LinearLayout>
</<com.test.libraries.SlidingLayer.SlidingLayer >
</io.codetail.widget.RevealFrameLayout>
</android.support.design.widget.CoordinatorLayout>
BoundedFrameLayout class:
public class BoundedFrameLayout extends FrameLayout {
private final int mBoundedWidth;
private final int mBoundedHeight;
public BoundedFrameLayout(Context context) {
super(context);
mBoundedWidth = 0;
mBoundedHeight = 0;
}
public BoundedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoundedView);
mBoundedWidth = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_width, 0);
mBoundedHeight = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_height, 0);
a.recycle();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Adjust width as necessary
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
if (mBoundedWidth > 0 && mBoundedWidth < measuredWidth) {
int measureMode = MeasureSpec.getMode(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedWidth, measureMode);
}
// Adjust height as necessary
int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
if (mBoundedHeight > 0 && mBoundedHeight < measuredHeight) {
int measureMode = MeasureSpec.getMode(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedHeight, measureMode);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
RevealFrameLayout class:
public class RevealFrameLayout extends FrameLayout implements RevealAnimator{
private Path mRevealPath;
private final Rect mTargetBounds = new Rect();
private RevealInfo mRevealInfo;
private boolean mRunning;
private float mRadius;
public RevealFrameLayout(Context context) {
this(context, null);
}
public RevealFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RevealFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mRevealPath = new Path();
}
#Override
public void onRevealAnimationStart() {
mRunning = true;
}
#Override
public void onRevealAnimationEnd() {
mRunning = false;
invalidate(mTargetBounds);
}
#Override
public void onRevealAnimationCancel() {
onRevealAnimationEnd();
}
#Override
public void setRevealRadius(float radius){
mRadius = radius;
mRevealInfo.getTarget().getHitRect(mTargetBounds);
invalidate(mTargetBounds);
}
#Override
public float getRevealRadius(){
return mRadius;
}
#Override
public void attachRevealInfo(RevealInfo info) {
mRevealInfo = info;
}
#Override
public SupportAnimator startReverseAnimation() {
if(mRevealInfo != null && mRevealInfo.hasTarget() && !mRunning) {
return ViewAnimationUtils.createCircularReveal(mRevealInfo.getTarget(),
mRevealInfo.centerX, mRevealInfo.centerY,
mRevealInfo.endRadius, mRevealInfo.startRadius);
}
return null;
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if(mRunning && child == mRevealInfo.getTarget()){
final int state = canvas.save();
mRevealPath.reset();
mRevealPath.addCircle(mRevealInfo.centerX, mRevealInfo.centerY, mRadius, Path.Direction.CW);
canvas.clipPath(mRevealPath);
boolean isInvalided = super.drawChild(canvas, child, drawingTime);
canvas.restoreToCount(state);
return isInvalided;
}
return super.drawChild(canvas, child, drawingTime);
}
}
I have this custom view:
public class TopBarHandler extends FrameLayout {
private Drawable mRightButtonSrc;
private boolean mShowRightButton;
private String mTitle;
private ImageButton mHamburgerButton;
private EllipsizingTextView mTitleTextView;
private ImageButton mRightButton;
private ProgressBar mProgressBar;
public TopBarHandler(final Context context, final AttributeSet attrs) {
super(context, attrs);
initView();
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.topbarMenu);
mShowRightButton = a.getBoolean(R.styleable.topbarMenu_showRightButton, false);
mRightButtonSrc = a.getDrawable(R.styleable.topbarMenu_rightButtonSrc);
mTitle = a.getString(R.styleable.topbarMenu_titleText);
}
public TopBarHandler(final Context context) {
super(context);
initView();
}
private void initView() {
View view = inflate(getContext(), R.layout.top_bar_layout, null);
mHamburgerButton = (ImageButton) findViewById(R.id.top_bar_hamburger_button);
mTitleTextView = (EllipsizingTextView) findViewById(R.id.top_bar_title);
mRightButton = (ImageButton) findViewById(R.id.top_bar_right_button);
mProgressBar = (ProgressBar) findViewById(R.id.top_bar_progress_bar);
addView(view);
}
public interface TopBarListener {
void onHamburgerButtonPressed();
void onRightButtonPressed();
}
}
With this layout definition:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/top_bar_layout"
android:layout_width="match_parent"
android:layout_height="#dimen/height_top_bar"
android:background="#drawable/gradient_top_bar"
android:gravity="center_vertical">
<ImageButton
android:id="#+id/top_bar_hamburger_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/margin_objects_top_bar"
android:src="#drawable/selector_menu_topbar"
android:background="#null"/>
<com.myproject.android.utilities.fonts.EllipsizingTextView
android:id="#+id/top_bar_title"
style="#style/bar_title_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="#string/CameraWizard_CameraWizard"
android:textSize="#dimen/menu_top_bar_title_size"
android:layout_marginLeft="#dimen/margin_top_bar_title"
android:layout_toLeftOf="#+id/top_bar_right_button"
android:layout_alignParentLeft="true"/>
<ImageButton
android:id="#+id/top_bar_right_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="#dimen/margin_objects_top_bar"
android:background="#drawable/top_bar_search"
android:visibility="invisible" />
<ProgressBar
android:id="#+id/top_bar_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="#dimen/margin_objects_top_bar"
android:indeterminate="false"
android:minHeight="50dp"
android:minWidth="50dp"
android:progress="1"
android:visibility="gone" />
</RelativeLayout>
And I want to put it in multiple layouts, so I do it like this:
<com.myproject.android.menu.TopBarHandler
android:layout_height="#dimen/height_top_bar"
android:layout_width="fill_parent"
/>
But the thing is, if I want to put this in multiple layouts (70+) then I have to specify the height and width in every single one of them. Is there a way to enforce the height in the customview itself?
If I dont specify height and width on the target layout, then I get an error. If I put wrap_content the height specified in the topbar_layout is ignored.
You need to implement onMeasure() in your custom view:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// What is the desired size of the view?
int desiredWidth = 250;
int desiredHeight = 250;
// The MeasureSpecs passed in will depend on the LayoutParams
// applied to the view in xml or programmatically
// Analyse the MeasureSpec for width and height separately like this:
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
switch (widthMode) {
case MeasureSpec.UNSPECIFIED:
widthSize = desiredWidth;
break;
case MeasureSpec.AT_MOST:
widthSize = Math.min(widthSize, desiredWidth);
break;
case MeasureSpec.EXACTLY:
break;
default:
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
switch (heightMode) {
case MeasureSpec.UNSPECIFIED:
heightSize = desiredHeight;
break;
case MeasureSpec.AT_MOST:
heightSize = Math.min(heightSize, desiredHeight);
break;
case MeasureSpec.EXACTLY:
break;
default:
}
// You must call setMeasuredDimension()
setMeasuredDimension(widthSize, heightSize);
}
I have following code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 1"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 2"
android:textSize="24sp" />
</LinearLayout>
that results:
How can I have equal size of View's height with its width (that is resulted by layout_weight)?
You have to override the onMeasure method set the same height as the height. Please see this question: Simple way to do dynamic but square layout
This is the complete solution that I come up with:
SquareLinearLayout.java :
public class SquareLinearLayout extends LinearLayout {
public SquareLinearLayout(Context context) {
super(context);
}
public SquareLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthDesc = MeasureSpec.getMode(widthMeasureSpec);
int heightDesc = MeasureSpec.getMode(heightMeasureSpec);
int size = 0;
if (widthDesc == MeasureSpec.UNSPECIFIED
&& heightDesc == MeasureSpec.UNSPECIFIED) {
size = getContext().getResources().getDimensionPixelSize(R.dimen.default_size); // Use your own default size, for example 125dp
} else if ((widthDesc == MeasureSpec.UNSPECIFIED || heightDesc == MeasureSpec.UNSPECIFIED)
&& !(widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED)) {
//Only one of the dimensions has been specified so we choose the dimension that has a value (in the case of unspecified, the value assigned is 0)
size = width > height ? width : height;
} else {
//In all other cases both dimensions have been specified so we choose the smaller of the two
size = width > height ? height : width;
}
setMeasuredDimension(size, size);
}
}
activity_my.xml :
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:listitem="#layout/item"
tools:context=".MyActivity">
</ListView>
item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.appsrise.squarelinearlayout.SquareLinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/holo_blue_bright">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 1"
android:textSize="24sp" />
</com.appsrise.squarelinearlayout.SquareLinearLayout>
<com.appsrise.squarelinearlayout.SquareLinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/holo_green_light">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 2"
android:textSize="24sp" />
</com.appsrise.squarelinearlayout.SquareLinearLayout>
</LinearLayout>
MyActivity.java :
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(new BaseAdapter() {
private LayoutInflater mInflater = LayoutInflater.from(MyActivity.this);
#Override
public int getCount() {
return 100;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = mInflater.inflate(R.layout.item, parent, false);
return convertView;
}
});
}
}
Simpler solution is to pass the width measurement specification into the height specification when calling onMeasure (or the other way around if you want the height to determine the square size).
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
public class SquareLinearLayout extends LinearLayout{
public SquareLinearLayout(Context context) {
super(context);
}
public SquareLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
// or super.onMeasure(heightMeasureSpec, heightMeasureSpec);
}
}
Xamarin version
[Register("SquareFrameLayout")]
public class SquareFrameLayout : LinearLayout
{
public SquareFrameLayout(Context context) : base(context)
{
}
public SquareFrameLayout(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public SquareFrameLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
var width = MeasureSpec.GetSize(widthMeasureSpec);
var height = MeasureSpec.GetSize(heightMeasureSpec);
var widthDesc = MeasureSpec.GetMode(widthMeasureSpec);
var heightDesc = MeasureSpec.GetMode(heightMeasureSpec);
if (widthDesc == MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
{
//size = Context.Resources.GetDimensionPixelSize(Resource.Dimension.default_size); // Use your own default size, for example 125dp
height = width = 0;
}
else if(heightDesc != MeasureSpecMode.Unspecified && widthDesc == MeasureSpecMode.Unspecified)
{
width = height;
}
else if (widthDesc != MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
{
height = width;
}
else
{
//In all other cases both dimensions have been specified so we choose the smaller of the two
var size = width > height ? height : width;
width = height = size;
}
SetMeasuredDimension(width, height);
}
and
[Register("SquareLinearLayout")]
public class SquareLinearLayout : LinearLayout
{
public SquareLinearLayout(Context context) : base(context)
{
}
public SquareLinearLayout(Context context, IAttributeSet attrs) : base(context, attrs)
{
}
public SquareLinearLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
var width = MeasureSpec.GetSize(widthMeasureSpec);
var height = MeasureSpec.GetSize(heightMeasureSpec);
var widthDesc = MeasureSpec.GetMode(widthMeasureSpec);
var heightDesc = MeasureSpec.GetMode(heightMeasureSpec);
if (widthDesc == MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
{
//size = Context.Resources.GetDimensionPixelSize(Resource.Dimension.default_size); // Use your own default size, for example 125dp
height = width = 0;
}
else if(heightDesc != MeasureSpecMode.Unspecified && widthDesc == MeasureSpecMode.Unspecified)
{
width = height;
}
else if (widthDesc != MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
{
height = width;
}
else
{
//In all other cases both dimensions have been specified so we choose the smaller of the two
var size = width > height ? height : width;
width = height = size;
}
SetMeasuredDimension(width, height);
}
}
You can do this also, If you need only one TextView needs to be square :
ViewTreeObserver vto = textview.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
textview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = textview.getMeasuredWidth();
int height = textview.getMeasuredHeight();
ViewGroup.LayoutParams params = textview.getLayoutParams();
if (width > height)
params.height = width;
else
params.width = height;
textview.setLayoutParams(params);
}
});
You can divide a LinearLayout into two equal LinearLayout like this..
<LinearLayout android:orientation="horizontal" android:layout_height="fill_parent" android:layout_width="fill_parent">
<LinearLayout android:layout_weight="1" android:layout_height="fill_parent" android:layout_width="fill_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 1"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout android:layout_weight="1" android:layout_height="fill_parent" android:layout_width="fill_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test 1"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
This will divide the LinearLayout into two equal LinearLayouts and each of these LinearLayouts will contain the TextViews
I've created a custom RelativeLayout that has two ImageView in it, one on top of the other, The first one is supposed to show the user selected image and the second on is shown up after he selected and acts as a delete button (small X icon), the problem that i have is even at the start of the application this custom view is invisible, but i can still click on it. and if i use a background for it i can see it.
Here is my Custom View class and XML
public class ImageViewWithIcon extends RelativeLayout{
public ImageView image, icon;
private final Context context;
public ImageViewWithIcon(final Context context)
{
super(context);
this.context = context;
}
public ImageViewWithIcon(final Context context, final AttributeSet attrs)
{
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.image_view_with_icon, this, true);
RelativeLayout rl = (RelativeLayout) getChildAt(0);
icon = (ImageView) findViewById(R.id.ImageViewWithIcon_icon);
image = (ImageView) findViewById(R.id.ImageViewWithIcon_image);
// image.setLayoutParams(new LayoutParams(400, 400));
this.context = context;
}
public ImageViewWithIcon(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
this.context = context;
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.new_message_picture_button);
int width;
if (getLayoutParams().width == android.view.ViewGroup.LayoutParams.WRAP_CONTENT)
width = bmp.getWidth();
else
if (getLayoutParams().width == android.view.ViewGroup.LayoutParams.MATCH_PARENT || getLayoutParams().width == android.view.ViewGroup.LayoutParams.FILL_PARENT)
width = MeasureSpec.getSize(widthMeasureSpec);
else
width = getLayoutParams().width;
int height = 100;
if (getLayoutParams().height == android.view.ViewGroup.LayoutParams.WRAP_CONTENT)
height = bmp.getHeight();
else
if (getLayoutParams().height == android.view.ViewGroup.LayoutParams.MATCH_PARENT || getLayoutParams().height == android.view.ViewGroup.LayoutParams.FILL_PARENT)
height = MeasureSpec.getSize(heightMeasureSpec);
else
height = getLayoutParams().height;
bmp.recycle();
setMeasuredDimension(width | MeasureSpec.EXACTLY, height | MeasureSpec.EXACTLY);
}}
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/ImageViewWithIcon_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:background="#drawable/new_message_picture_button" />
<ImageView
android:id="#+id/ImageViewWithIcon_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/ImageViewWithIcon_image"
android:visibility="visible"
android:src="#drawable/new_message_close_picture"/>
</RelativeLayout>
</merge>
The first line in onMessure has bmp with width and height of 234px
even if I create a method like setImage() to call it from the Activity, the image is set but it is still invisible.
Do you mean?
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageViewWithIcon
android:id="#+id/ImageViewWithIcon_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:background="#drawable/new_message_picture_button" />
<ImageViewWithIcon
android:id="#+id/ImageViewWithIcon_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/ImageViewWithIcon_image"
android:visibility="visible"
android:src="#drawable/new_message_close_picture"/>
I am having trouble in getting the GridView content height programmatically since I am placing it inside a ScrollView, I just need to stretch the GridView height dynamically by getting its content height in PIXELS. Here's what I did:
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
System.out.println("...111Height..."+gridView.getMeasuredWidth());
}
but I want to obtain the value inside OnCreate so that I can feed it to layoutParams.height in:
GridView gridView = (GridView) findViewById(R.id.gridview_module);
ViewGroup.LayoutParams layoutParams = gridView.getLayoutParams();
layoutParams.height = convertDpToPixels(iDontKnowWhatToPutHere, this);
gridView.setLayoutParams(layoutParams);
and the method to convert from pixels to dp:
public static int convertDpToPixels(float dp, Context context) {
Resources resources = context.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
resources.getDisplayMetrics());
}
EDIT:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainLayout"
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"
tools:context=".SecondActivity" >
<ScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="0"
android:layout_weight="1"
android:fillViewport="true"
android:scrollbars="none" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<com.example.ExpandableHeightGridView
android:id="#+id/gridview_module"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#id/tv"
android:layout_weight="1"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="3"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" />
<Button
android:id="#+id/dial_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/gridview_module"
android:onClick="dialPhone"
android:text="Dial Phone" />
</LinearLayout>
</ScrollView>
To achieve this you need to create CustomGridview like this
public class CustomGridView extends GridView {
private int old_count;
private android.view.ViewGroup.LayoutParams params;
private boolean isExpandFully = false;
private int verticleSpacing = 4;
private int noOfCollumns = 1;
public int getNumColumns() {
return noOfCollumns;
}
public void setNoOfCollumns(int noOfCollumns) {
this.noOfCollumns = noOfCollumns;
}
public int getVerticleSpacing() {
return verticleSpacing;
}
public void setVerticleSpacing(int verticleSpacing) {
this.verticleSpacing = verticleSpacing;
}
public void setExpandFully(boolean isExpandFully) {
this.isExpandFully = isExpandFully;
}
public CustomGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomGridView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CustomGridView(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
if (attrs != null) {
String namespace = "http://schemas.android.com/apk/res/android";
noOfCollumns = attrs.getAttributeIntValue(namespace, "numColumns", 1);
}
}
#Override
protected void onDraw(Canvas canvas) {
setVerticalSpacing(getVerticleSpacing());
if (isExpandFully) {
try {
if (getCount() != old_count) {
old_count = getCount();
params = getLayoutParams();
int len = (getCount() % getNumColumns() == 0 ? getCount() / getNumColumns() : getCount() / getNumColumns() + 1);
params.height = 0;
for (int i = 0; i < len; i++) {
params.height = params.height + (old_count > 0 ? getChildAt(0).getHeight() + getVerticleSpacing() : 0);
}
params.height += 10;
setLayoutParams(params);
}
} catch (Exception e) {
}
}
super.onDraw(canvas);
}
}
how to use
CustomGridView myGridview = (CustomGridView)findViewById(R.id.customGridview);
myGridview.setExpandFully(true);