danvim / Procal

2 stars 0 forks source link

Dynamically resize layouts to fit screen size #2

Closed danvim closed 7 years ago

danvim commented 7 years ago

Add code to dynamically resize layouts to fit screen size

dipsywong98 commented 7 years ago

mainActivity.java

package dcheungaa.procal;

import android.app.Dialog;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.view.Display;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private int width,height;
    private RelativeLayout contentMain;
    private LinearLayout llScreen;

    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);*/

        /*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });*/

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, /*toolbar,*/ R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        TextView matrixDisplay = (TextView) findViewById(R.id.matrixDisplay);
        final Typeface FONT_FX50 = Typeface.createFromAsset(getAssets(), "fonts/Fx50.otf");
        matrixDisplay.setTypeface(FONT_FX50);
        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_settings) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            return true;
        } else if (id == R.id.nav_save) {

        } else if (id == R.id.nav_history) {

        } else if (id == R.id.nav_share) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    public Action getIndexApiAction() {
        Thing object = new Thing.Builder()
                .setName("Main Page") // TODO: Define a title for the content shown.
                // TODO: Make sure this auto-generated URL is correct.
                .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
                .build();
        return new Action.Builder(Action.TYPE_VIEW)
                .setObject(object)
                .setActionStatus(Action.STATUS_TYPE_COMPLETED)
                .build();
    }

    @Override
    public void onStart() {
        super.onStart();
        int max;
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        width = size.x;
        height = size.y;
        contentMain = (RelativeLayout) findViewById(R.id.content_main);
        llScreen = (LinearLayout) findViewById(R.id.llScreen);

        LinearLayout upper=llScreen;
        Button preBtn;

        for (int i=0 ;i<6 ; i++){
            LinearLayout row = new LinearLayout(this);
            RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);

            if (i==0) rlp.addRule(RelativeLayout.BELOW,R.id.llScreen);
            else rlp.addRule(RelativeLayout.BELOW,upper.getId());

            row.setLayoutParams(rlp);

            Button btn= new Button(this);
            preBtn = btn;
            if (i<3) max=6;
            else max=5;
            for (int j=0; j<max ; j++){

                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                        RelativeLayout.LayoutParams.WRAP_CONTENT,
                        RelativeLayout.LayoutParams.WRAP_CONTENT);
                if (j==0) lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                else lp.addRule(RelativeLayout.RIGHT_OF,preBtn.getId());
                preBtn = btn;

                btn.setLayoutParams(lp);
                btn.getLayoutParams().width=width/max;

                btn.setId(i*10+j);

                btn.setText(Integer.toString(10*i+j)+" "+Integer.toString(btn.getMinWidth()));

                row.addView(btn);
                if (j<6)btn= new Button(this);
            }

            contentMain.addView(row);
            row.setId(i+1);
            upper=row;
        }

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        AppIndex.AppIndexApi.start(client, getIndexApiAction());
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        AppIndex.AppIndexApi.end(client, getIndexApiAction());
        client.disconnect();
    }
}

linearLayout llButtonPanel was commented

danvim commented 7 years ago

@dipsywong98 Can you explain your code and excerpt the necessary code to make it more concise?

dipsywong98 commented 7 years ago

get screen size

Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y;

set button width btn.getLayoutParams().width=width/max;

dipsywong98 commented 7 years ago

finally done T.T

//color define here
//I dunno why color in res was loaded with wrong color
private int colorAccent=Color.parseColor("#FF9800");                     //<--
private int colorPurple=Color.parseColor("#C51162");                     //<--

//use this listener to get the height of llScreen and matrixdiplay
    //if use oncreate, height will be 0 as they are still not well defined by the program
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {                     //<--
        super.onWindowFocusChanged(hasFocus);                     //<--

        //get windows' height and width
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        width = size.x;
        height = size.y;

        //define the elements defined in layout
        TextView tv = (TextView)findViewById(R.id.matrixDisplay);                     //<--
        contentMain = (RelativeLayout) findViewById(R.id.content_main);
        llScreen = (LinearLayout) findViewById(R.id.llScreen);

        //the height of space left to place keyboard
        int rows_height=height-llScreen.getHeight()-findViewById(R.id.matrixDisplay).getHeight();                     //<--

        //define the height of two types of button,  fn : large =  3.8 : 4.5
        double btn_large_height= rows_height*4.5/8.3/4;                     //<--
        double btn_fn_height = rows_height*3.8/8.3/4;                     //<--

        //for debug, display the height of two types of button
        // tv.setText("("+width+","+height+") ("+btn_large_height+","+btn_fn_height+")");                     //<--

        LinearLayout rows = (LinearLayout) findViewById(R.id.rows);                     //<--
        rows.setOrientation(LinearLayout.VERTICAL);                     //<--

        String json = "";

        InputStream in_s = getResources().openRawResource(R.raw.keypad);

        try {
            byte[] b = new byte[in_s.available()];
            in_s.read(b);
            json = new String(b);
        } catch (IOException e) {

        }

        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();

        Gson gson=new Gson();
        JsonHelper.KeypadRows keypadRows = gson.fromJson(jsonObject, JsonHelper.KeypadRows.class);

        for (JsonHelper.Key[] keys : keypadRows.rows) {
            LinearLayout row = new LinearLayout(this);
            row.setOrientation(LinearLayout.HORIZONTAL);

            row.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
            for (JsonHelper.Key key : keys) {
                Button btn = new Button(this);

                //apply styles defined in json
                btn.setText(key.key);

                if (key.style.contains("Orange")) btn.setTextColor(colorAccent);                     //<--change color
                else if (key.style.contains("Purple")) btn.setTextColor(colorPurple);                     //<--change color

                btn.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f));//our honorable leader Daniel's code

                if (key.style.contains("Large")) btn.getLayoutParams().height = (int)btn_large_height ;                     //<--set height of button Large
                if (key.style.contains("Fn")) btn.getLayoutParams().height = (int)btn_fn_height ;                     //<--set height of button Fn
                btn.getLayoutParams().width = (int) width/keys.length;                     //<--set btn width, btn width may change after changing the height
                btn.setGravity(Gravity.CENTER);                     //<--align to the center
                row.addView(btn);
                final Button fbtn=btn;                     //<--for passing btn into the listener function for dynamic padding

                //listener to hear if the button text take more than 1 line, if yes, decrease the padding to see if fit to 1 line
                btn.getViewTreeObserver().addOnGlobalLayoutListener(new                      ViewTreeObserver.OnGlobalLayoutListener() {                     //<--set listener to the btn
                    @Override                     //<--
                    public void onGlobalLayout() {                     //<--define listener function
                        //if take more than 1 line
                        if (fbtn.getLineCount()>1){                     //<--check if text in btn more than 1  line
                            //shrink padding
                             fbtn.setPadding(fbtn.getPaddingLeft()-1,fbtn.getPaddingTop(),fbtn.getPaddingRight()-1,fbtn.getPaddingBottom());                     //<--shrink padding
                        }                     //<--
                        // if already take 1 line only, remove the listener                     //<--
                        else fbtn.getViewTreeObserver().removeGlobalOnLayoutListener(this);                     //<--
                    }                     //<--
                });                     //<--

            }                     
            rows.addView(row);
        }

    }

    //on start is almost useless now
    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        AppIndex.AppIndexApi.start(client, getIndexApiAction());
    }
dipsywong98 commented 7 years ago

I amend the keys in JSON to make it look more beautiful

{
  "rows":[
    [
      {
        "key": "SHIFT",
        "style": "Fn"
      },
      {
        "key": "ALPHA",
        "style": "Fn"
      },
      {
        "key": "CONST",
        "style": "Fn"
      },
      {
        "key": "MDOE",
        "style": "Fn"
      },
      {
        "key": "d/dx",
        "style": "Fn",
        "shift": "integration"
      },
      {
        "key": "FUNC",
        "style": "Fn_Orange"
      }
    ],
    [
      {
        "key": "a b/c",
        "style": "Fn",
        "shift": "d/c"
      },
      {
        "key": "√",
        "style": "Fn"
      },
      {
        "key": "x^2",
        "style": "Fn"
      },
      {
        "key": "^",
        "style": "Fn",
        "shift": "x_root"
      },
      {
        "key": "log",
        "style": "Fn",
        "shift": "10^x"
      },
      {
        "key": "ln",
        "style": "Fn",
        "shift": "e^x"
      }
    ],
    [
      {
        "key": "(-)",
        "style": "Fn",
        "shift": "angle"
      },
      {
        "key": "° '  \"",
        "style": "Fn",
        "shift": "<-"
      },
      {
        "key": "hyp",
        "style": "Fn"
      },
      {
        "key": "sin",
        "style": "Fn",
        "shift": "asin"
      },
      {
        "key": "cos",
        "style": "Fn",
        "shift": "acos"
      },
      {
        "key": "tan",
        "style": "Fn",
        "shift": "atan"
      }
    ],
    [
      {
        "key": "REC",
        "style": "Fn",
        "shift": "str"
      },
      {
        "key": "ENG",
        "style": "Fn",
        "shift": "<-"
      },
      {
        "key": "(",
        "style": "Fn",
        "shift": "%"
      },
      {
        "key": ")",
        "style": "Fn",
        "shift": "abs"
      },
      {
        "key": ",",
        "style": "Fn",
        "shift": ";"
      },
      {
        "key": "M+",
        "style": "Fn",
        "shift": "M-"
      }
    ],
    [
      {
        "key": "7",
        "style": "Large_More",
        "shift": "constant"
      },
      {
        "key": "8",
        "style": "Large"
      },
      {
        "key": "9",
        "style": "Large_More",
        "shift": "clear"
      },
      {
        "key": "DEL",
        "style": "Purple_Large_Text_More",
        "shift": "ins"
      },
      {
        "key": "AC",
        "style": "Purple_Large_Text"
      }
    ],
    [
      {
        "key": "4",
        "style": "Large"
      },
      {
        "key": "5",
        "style": "Large"
      },
      {
        "key": "6",
        "style": "Large"
      },
      {
        "key": "✘",
        "style": "Large",
        "shift": "nPr"
      },
      {
        "key": "/",
        "style": "Large",
        "shift": "nCr"
      }
    ],
    [
      {
        "key": "1",
        "style": "Large"
      },
      {
        "key": "2",
        "style": "Large"
      },
      {
        "key": "3",
        "style": "Large"
      },
      {
        "key": "+",
        "style": "Large",
        "shift": "pol"
      },
      {
        "key": "-",
        "style": "Large",
        "shift": "rec"
      }
    ],
    [
      {
        "key": "0",
        "style": "Large",
        "shift": "rnd"
      },
      {
        "key": ".",
        "style": "Large",
        "shift": "ran"
      },
      {
        "key": "EXP",
        "style": "Large_Text",
        "shift": "pi"
      },
      {
        "key": "ANS",
        "style": "Large_Text",
        "shift": "DRG"
      },
      {
        "key": "EXE",
        "style": "Large_Text"
      }
    ]
  ]
}
danvim commented 7 years ago

@dipsywong98 can you mark the line changed with comments, like: //<-- after that line?

dipsywong98 commented 7 years ago

basic dynamic layout done in fa00abf87b46dc1f618fdb309b1d7b71e7d94571

alignment of ... above the button can be improved