Symmetry

You chose a colour, then click in a grid. The resulting design gets displayed, plus various symmetries of it.

This is similar to the Mosaic app, but I've coded it in a different (and better!) way.

Stringsapp/res/values/strings.xml
Screen formatapp/res/layout/activity_main.xml
Code for appapp/java/com.(the project name)/MainActivity
Code for palette gridviewapp/java/com.(the project name)/ImagePalette
Code for tessera gridviewapp/java/com.(the project name)/ImageTessera



app/manifests/AndroidManifest.xml - to force portrait orientation

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.edkins.mosaic" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>


app/res/drawable - pictures

There are a number of colour files, called "colour0", "colour1", "colour2" etc. They are loaded into an array defined in in app/java/com.(the project name)/MainActivity and used in app/java/com.(the project name)/ImagePalette and app/java/com.(the project name)/ImageTessera. The number of them (10) is referenced in app/res/layout/activity_main.xml.

There is one more colour file, called "colourx", which is all white.




app/res/mipmap/ic_launcher.png/ - icon for launching app




app/res/values/strings.xml - strings

<resources> <string name="app_name">Symmetry</string> <string name="howTo">Choose colour, tap in grid.</string> <string name="clearMessage">new</string> <string name="big">big</string> <string name="small">small</string> <string name="symm0">Reflection (mirror)</string> <string name="symm1">Rotation (turn)</string> <string name="symm2">Translation (move)</string> <string name="num0">4 areas</string> <string name="num1">2 vertical</string> <string name="num2">2 horizontal</string> </resources>


app/res/layout/activity_main.xml - screen format

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/relLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <GridView android:id="@+id/paletteView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numColumns="10" /> <TextView android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/howTo" android:layout_below="@id/paletteView" /> <GridView android:id="@+id/mosaicView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/message" /> <Button android:id="@+id/clearButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clearMessage" android:onClick="doClear" android:layout_below="@id/mosaicView" /> <Button android:id="@+id/sizeButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/small" android:onClick="changeSize" android:layout_below="@id/clearButton" /> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/symm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_below="@id/mosaicView" android:layout_toRightOf="@id/clearButton" android:layout_toEndOf="@id/clearButton" > <RadioButton android:id="@+id/symm0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/symm0" android:onClick="clickSymm0" /> <RadioButton android:id="@+id/symm1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/symm1" android:onClick="clickSymm1" /> <RadioButton android:id="@+id/symm2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/symm2" android:onClick="clickSymm2" /> </RadioGroup> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_below="@id/mosaicView" android:layout_toRightOf="@id/symm" android:layout_toEndOf="@id/symm" > <RadioButton android:id="@+id/num0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/num0" android:onClick="clickNum0" /> <RadioButton android:id="@+id/num1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/num1" android:onClick="clickNum1" /> <RadioButton android:id="@+id/num2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/num2" android:onClick="clickNum2" /> </RadioGroup> </RelativeLayout>


app/java/com.(the project name)/MainActivity - main code for app

package com.edkins.symmetry; import ... public class MainActivity extends AppCompatActivity { // colour selected - starts as red int paint = 1; int symmetry = 0; public static int number = 0; public static int size = 0; public static int whole = 10; public static int half = whole / 2; // tiles - for setting up tessera public static int [] tile = new int [16 * 16]; // Colours public static Integer[] palette = { R.drawable.colour0, R.drawable.colour1, R.drawable.colour2, R.drawable.colour3, R.drawable.colour4, R.drawable.colour5, R.drawable.colour6, R.drawable.colour7, R.drawable.colour8, R.drawable.colour9 }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GridView palette = (GridView) findViewById(R.id.paletteView); palette.setAdapter(new ImagePalette(this)); palette.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { processPaletteClick(position); } }); GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setNumColumns(whole); mosaic.setAdapter(new ImageTessera(this)); mosaic.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { processMosaicClick(position); } }); RadioButton symm = (RadioButton) findViewById(R.id.symm0); symm.setChecked(true); symmetry = 0; RadioButton num = (RadioButton) findViewById(R.id.num0); num.setChecked(true); number = 0; } public void processPaletteClick(int position) { paint = position; } public void processMosaicClick(int position) { int col = 0; if (tile[position] != paint) {col = paint;} calcAll(position, col); GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setAdapter(new ImageTessera(this)); } public void doClear(View view) { for (int i=0; i<(whole * whole); i++) {tile[i] = 0;} GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setAdapter(new ImageTessera(this)); } public void calcAll(int position, int col) { int y1 = position / whole; int x1 = position - (y1 * whole); if (number==0 && x1 >= half) {return;} if (number==0 && y1 >= half) {return;} if (number==1 && x1 >= half) {return;} if (number==2 && y1 >= half) {return;} tile[position] = col; int x2=0; int x3=0; int x4=0; int y2=0; int y3=0; int y4=0; if (number==0) { if (symmetry == 0) { x2 = whole - 1 - x1; y2 = y1; x3 = x1; y3 = whole - 1 - y1; x4 = whole - 1 - x1; y4 = whole - 1 - y1; } else if (symmetry == 1) { x2 = whole - 1 - y1; y2 = x1; x3 = y1; y3 = whole - 1 - x1; x4 = whole - 1 - x1; y4 = whole - 1 - y1; } else if (symmetry == 2) { x2 = x1 + half; y2 = y1; x3 = x1; y3 = y1 + half; x4 = x1 + half; y4 = y1 + half; } tile[y2 * whole + x2] = col; tile[y3 * whole + x3] = col; tile[y4 * whole + x4] = col; } else if (number==1) { if (symmetry == 0) { x2 = whole - 1 - x1; y2 = y1; } else if (symmetry == 1) { x2 = whole - 1 - x1; y2 = whole - 1 - y1; } else if (symmetry == 2) { x2 = x1 + half; y2 = y1; } tile[y2 * whole + x2] = col; } else if (number==2) { if (symmetry == 0) { x2 = x1; y2 = whole - 1 - y1; } else if (symmetry == 1) { x2 = whole - 1 - x1; y2 = whole - 1 - y1; } else if (symmetry == 2) { x2 = x1; y2 = y1 + half; } tile[y2 * whole + x2] = col; } } public void clickSymm0(View view) {symmetry = 0; redo();} public void clickSymm1(View view) {symmetry = 1; redo();} public void clickSymm2(View view) {symmetry = 2; redo();} // redo screen public void redo() { for (int i=0; i < (whole * whole); i++) {calcAll(i, tile[i]);} GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setAdapter(new ImageTessera(this)); } public void clickNum0(View view) {number = 0; clearMost(); redo();} public void clickNum1(View view) {number = 1; clearMost(); redo();} public void clickNum2(View view) {number = 2; clearMost(); redo();} // clear most of screen public void clearMost() { for (int i=0; i<(whole * whole); i++) { int y = i / whole; int x = i - (y * whole); if (x>=half || y>=half) {tile[i] = 0;} } GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setAdapter(new ImageTessera(this)); } // change size of element public void changeSize(View view) { Button message = (Button) findViewById(R.id.sizeButton); if (size==1) { size=0; whole = 10; half = whole / 2; message.setText(getString(R.string.small)); } else { size=1; whole = 16; half = whole / 2; message.setText(getString(R.string.big)); } for (int i=0; i<(whole * whole); i++) {tile[i] = 0;} GridView mosaic = (GridView) findViewById(R.id.mosaicView); mosaic.setNumColumns(whole); mosaic.setAdapter(new ImageTessera(this)); } }


app/java/com.(the project name)/ImagePalette - code for palette gridview. You create this new file by right-clicking on the MainActvity and select New, then Java class

package com.edkins.symmetry; import ... public class ImagePalette extends BaseAdapter { private AppCompatActivity mContext; public ImagePalette(AppCompatActivity c) {mContext = c;} public int getCount() {return MainActivity.palette.length;} public Object getItem(int position) {return null;} public long getItemId(int position) {return 0;} // create new ImageView for palette public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(mContext); } else { imageView = (ImageView) convertView; } // initialise the view element (to one of the colours) imageView.setImageResource(MainActivity.palette[position]); return imageView; } }


app/java/com.(the project name)/ImageTessera - code for tessera gridview - a new file, see above

package com.edkins.symmetry; import ... public class ImageTessera extends BaseAdapter { private AppCompatActivity mContext; public ImageTessera(AppCompatActivity c) {mContext = c;} public int getCount() {return MainActivity.whole * MainActivity.whole;} public Object getItem(int position) {return null;} public long getItemId(int position) {return 0;} // create new ImageView for tessera public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(mContext); // set height and width of image dependent on screen width RelativeLayout rel = (RelativeLayout) mContext.findViewById(R.id.relLayout); int w = rel.getWidth() / MainActivity.whole; imageView.setLayoutParams(new GridView.LayoutParams(w, w)); } else { imageView = (ImageView) convertView; } // set it to the colour in the tile array int sub = MainActivity.tile[position]; int y = position / MainActivity.whole; int x = position - (y * MainActivity.whole); int ok; if (sub>0) {ok = 1;} else if (MainActivity.number==0 && x < MainActivity.half && y < MainActivity.half) {ok = 1;} else if (MainActivity.number==1 && x < MainActivity.half) {ok = 1;} else if (MainActivity.number==2 && y < MainActivity.half) {ok = 1;} else {ok = 0;} if (ok == 1) {imageView.setImageResource(MainActivity.palette[sub]);} else {imageView.setImageResource(R.drawable.colourx);} return imageView; } }


Index to my other websites

© Jo Edkins 2016