-1

In an attempt to create a square view (in which the width is permitted to vary but the height is set equal to the width - green in the screen shot) I have created extended view and overridden onMeasure as per another stack overflow question .

Doing so correctly forces the view to remain square. However; it does not "play nice" with other elements on the screen. Pushing them offscreen if the SquareView is larger than it naturally would be. This is demonstrated in the following screen shot. A SquareView is followed by a ScrollView, which has the descending numbers 23-1 within it. When SquareView overrides onMeasure the last few numbers are cut off even when the ScrollView is scrolled to the very bottom. When it isn't overridden everything fits perfectly (but of SquareView isn't square).

I believe that everything else is having its size determined based on the natural size of the SquareView and then my resizing of it is messing everything up.

How can I create a view that resizes itself to be square without pushing other elements off the screen?

enter image description here

Additionally to cutting off the end; when scrolling the scroll bar is clearly wrong and extends off screen.

SquareView:

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;

public class SquareView extends View{


    public SquareView(Context context, AttributeSet aSet) {

            super(context, aSet);
            this.setBackgroundColor(Color.GREEN);
     }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

        setMeasuredDimension( width, width);
    }

}

XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

     android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:orientation="vertical" >

    <com.example.resizeissue.SquareView

            android:layout_width="fill_parent"

            android:layout_height="0dp"

            android:layout_weight="1"

            android:layout_margin="20dip"

            android:id="@+id/the_canvas"/>

          <ScrollView
          android:layout_width="fill_parent"
          android:layout_height="0dp" 
          android:layout_weight="1"
          >
             <LinearLayout
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="vertical"

               >

                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="13\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="12\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="11\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="10\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="9\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="8\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="7\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="6\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="5\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="4\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="3\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="2\n\n\n"
                        />
                   <TextView
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_gravity="center"
                       android:text="end"
                        />



            </LinearLayout>
        </ScrollView>

</LinearLayout>

MainActivity (pretty much standard):

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
        }
    }

}
Community
  • 1
  • 1
Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
  • Have you tried setting the layout_height attribute of your square view to wrap_content? I would suggest using a RelativeLayout, and putting `android:layout_below="@id/the_canvas"` on your ScrollView, but I think both methods will result in the ScrollView being pushed off the screen in landscape orientation. – Dave Morrissey Jun 09 '14 at 17:35
  • @DaveMorrissey For this I'm locking the application to landscape so thats not an issue. I'll have a look at both those options now – Richard Tingle Jun 09 '14 at 17:37
  • @DaveMorrissey Setting layout_height attribute of the square view to "wrap_content" causes the "natural height" to be zero, so the ScrollView ends up mostly behind the (resized) squareView. RelativeLayout however behaves exactly as I want it to. Would you like to write up the answer? (If not I shall but I'm not 100% sure *why* this works and linear layout doesn't, just that it does) – Richard Tingle Jun 09 '14 at 17:52
  • By landscape I mean portrait – Richard Tingle Jun 09 '14 at 17:54
  • I'm not sure either, it was a gut feeling :-) – Dave Morrissey Jun 09 '14 at 18:22
  • @Dave good gut feeling. I'll leave it for a while to see if anyone comes up with a reason and if not I'll post a "Well this works \*shrugs\*" answer – Richard Tingle Jun 09 '14 at 18:28
  • @DaveMorrissey I found out the real issue; I was giving `SquareView` an `android:layout_weight="1"` within the xml. This in combination with explicitly setting the height created an impossible situation (both `SquareView` and `ScrollView` having weight 1 forced both to be the same size; hence exceeding the screen). When I changed to relativeLayout I was obliged to remove the weight and the issue resolved itself – Richard Tingle Jun 09 '14 at 21:40

2 Answers2

0

The issue here was using a weight to define the height of SquareView as well as explicitly setting its height. This actually makes sense not to end well because you can't simultaneously define the remaing space being split by weight and explicitly setting one of the elements sizes without something having to give.

So the following changes needed to be made

<com.example.resizeissue.SquareView

        android:layout_width="fill_parent"

        android:layout_height="0dp"

        android:layout_margin="20dip"

        android:id="@+id/the_canvas"/>

      <ScrollView
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      >
      .......

This results in everything fitting within the space nicely

Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
-1

From http://www.jayway.com/2012/12/12/creating-custom-android-views-part-4-measuring-and-how-to-force-a-view-to-be-square/ (I googled for square view...)

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int size = 0;
    int width = getMeasuredWidth();
    int height = getMeasuredHeight();

    if (width > height) {
        size = height;
    } else {
        size = width;
    }
    setMeasuredDimension(size, size);
}
Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
ElDuderino
  • 3,253
  • 2
  • 21
  • 38
  • This is pretty much the same as the code in my question, yours has ` super.onMeasure(widthMeasureSpec, heightMeasureSpec);` unlike mine but adding that to mine makes no difference – Richard Tingle Jun 09 '14 at 21:21