Search code examples
androidcanvasviewzoomingscale

View not showing all content after scaling down


After using the View.setScaleX() and View.setScaleY() methods to make my view smaller, the result only shows the content that was already displayed, leaving out the rest that didn't fit on the screen when it was zoomed in. How can I force it to show the rest of the content?

XML: activity_main.xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/table"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

JAVA: MainActivity.java

package com.example.zoom;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class MainActivity extends Activity {

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

        TableLayout table = (TableLayout) findViewById(R.id.table);

        int textViewSize = 100;
        int tableColCount = 15;
        int tableRowCount = 15;

        for (int row = 0; row < tableRowCount; row++) {
            TableRow tr = new TableRow(this);
            for (int col = 0; col < tableColCount; col++) {
                TextView textView = new TextView(this);
                textView.setText("" + row + "." + col);
                textView.setTextSize(20.0f);
                tr.addView(textView, textViewSize, textViewSize);
            } // for
            table.addView(tr);
        } // for
    }

    @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) {

        LinearLayout table = (LinearLayout) findViewById(R.id.table);

        switch (item.getItemId()) {

            case R.id.action_zoom_in:
                table.setScaleX(1.0f);
                table.setScaleY(1.0f);
                break;
            case R.id.action_zoom_out:
                table.setScaleX(0.25f);
                table.setScaleY(0.25f);
                break;
        } // switch
        return true;
    }
}

SCREEN SHOTS: Zoomed In | Zoomed Out

I noticed this question was very much the same as mine, but there was no code nor answer.


Solution

  • As it turns out setting the size of the view manually (instead of using wrap_content) did the trick. This is all it really took:

    FrameLayout.LayoutParams tableLP = new FrameLayout.LayoutParams(
        textViewSize * tableColCount, textViewSize * tableRowCount);
    table.setLayoutParams(tableLP);
    

    I also set the pivot point to 0 to keep the view in the top left corner.

    table.setPivotX(0);
    table.setPivotY(0);
    

    In regards to pskink (who commented on my original question) I looked into animations and discovered that using a ViewPropertyAnimator did a pretty nice job as well. To use this class you just call View.animate().

    After setting the size of the view that will be scaled, and the pivot point of that view, you can either use the basic scaling method with no animation,

    // zoom in by 50%
    float scale = 0.5f;
    view.setScaleX(table.getScaleX() + scale);
    view.setScaleY(table.getScaleY() + scale);
    

    or the scaling method with animation.

    // zoom in by 50%
    float scale = 0.5f;
    table.animate().scaleXBy(scale).scaleYBy(scale).setDuration(0).start();
    

    Here is a full example of the program in the original question:

    package com.example.zoom;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.FrameLayout;
    import android.widget.TableLayout;
    import android.widget.TableRow;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            TableLayout table = (TableLayout) findViewById(R.id.table);
    
            int textViewSize = 100;
            int tableColCount = 15;
            int tableRowCount = 15;
    
            for (int row = 0; row < tableRowCount; row++) {
                TableRow tr = new TableRow(this);
                for (int col = 0; col < tableColCount; col++) {
                    TextView textView = new TextView(this);
                    textView.setText(row + "." + col);
                    textView.setTextSize(20.0f);
                    tr.addView(textView, textViewSize, textViewSize);
                } // for
                table.addView(tr);
            } // for
    
            // manually set the size to make sure the entire view is drawn and will be seen when scaled down
            FrameLayout.LayoutParams tableLP = new FrameLayout.LayoutParams(textViewSize * tableColCount, textViewSize * tableRowCount);
            table.setLayoutParams(tableLP);
        }
    
        @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) {
    
            TableLayout table = (TableLayout) findViewById(R.id.table);
            // set default scale to 0 in case no scale occurs
            float scale = 0.0f;
    
            switch (item.getItemId()) {
    
                case R.id.action_zoom_in:
                    scale = 0.5f;
                    break;
                case R.id.action_zoom_out:
                    // use negative to decrease the scale
                    scale = -0.5f;
                    break;
            } // switch
    
            // set pivot to 0 to keep view in the top left corner
            table.setPivotX(0);
            table.setPivotY(0);
            // add new scale with current scale to get View.scaleBy() equivalent
            table.setScaleX(table.getScaleX() + scale);
            table.setScaleY(table.getScaleY() + scale);
    //      could use an animation instead
    //      table.animate().scaleXBy(scale).scaleYBy(scale).setDuration(0).start();
            return true;
        }
    }