Skip to content

Commit

Permalink
Update for Release 0.0.0.4
Browse files Browse the repository at this point in the history
Updated Example App to allow adding multiple different examples.
Add example of using FixedHeaderSubTableLayout directly for modular multiple tables.
Created a Utils Class for width aligning methods, so they can be used independently.
  • Loading branch information
Zardozz committed Jan 10, 2022
1 parent 8a515fd commit 2072405
Show file tree
Hide file tree
Showing 15 changed files with 790 additions and 337 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ FixedHeaderTableLayout is similar in construction and use as to Android's TableL
- [x] Each row height value will be automatically adjusted to fit the largest cell in the row.
- [x] Support for API 16 upwards

## Bonus Feature
The FixedHeaderSubTableLayout behaves like a normal TableLayout But it gives you direct access to the cell sizes.

Thus it is possible to align cells between independent tables allowing you to build more complicated tables with borders easier,
easily split tables across print pages, viewpager, etc by using modular groups of aligned tables next to each other.
It also allows a form of column spanning, a column in one table can be made to be the size of multiple columns
in the adjacent table, so it looks like column spanning.

Some examples in the MultiTableExample in the Example App.

<p align="center">
<img src="https://raw.githubusercontent.com/Zardozz/FixedHeaderTableLayout/master/art/MultiTableExample.png">
</p>

## Feature TODO list
- [x] Scale around pinch center.
- [x] Corner layout location and layout direction to support Right to Left Languages.
Expand Down Expand Up @@ -61,7 +75,7 @@ allprojects {
Add the following dependency into your module's `build.gradle`:
```
dependencies {
implementation 'com.github.Zardozz:fixedheadertablelayout:0.0.0.3'
implementation 'com.github.Zardozz:fixedheadertablelayout:0.0.0.4'
}
```

Expand Down
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ android {
applicationId "com.github.zardozz.fixedheadertablelayoutsample"
minSdkVersion 16
targetSdkVersion 30
versionCode 3
versionName "0.0.0.3"
versionCode 4
versionName "0.0.0.4"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -94,6 +94,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation project(path: ':fixedheadertablelayout')
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
Expand Down
34 changes: 8 additions & 26 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,28 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ MIT License
~
~ Copyright (c) 2021 Andrew Beck
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in all
~ copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
~ SOFTWARE.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.zardozz.fixedheadertablelayoutsample">

Expand All @@ -33,13 +9,19 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="false"
android:theme="@style/Theme.FixedHeaderTableLayout">
<activity android:name="com.github.zardozz.fixedheadertablelayoutsample.MainActivity"
>
<activity
android:name=".MultiTableExampleActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainExampleActivity" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2021 Andrew Beck
* Copyright (c) 2022 Andrew Beck
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -24,241 +24,28 @@

package com.github.zardozz.fixedheadertablelayoutsample;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.github.zardozz.FixedHeaderTableLayout.*;

import java.lang.ref.SoftReference;
import java.util.Locale;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

private FixedHeaderTableLayout fixedHeaderTableLayout;
private ProgressBar pgsBar;

FixedHeaderSubTableLayout mainTable;
FixedHeaderSubTableLayout columnHeaderTable;
FixedHeaderSubTableLayout rowHeaderTable;
FixedHeaderSubTableLayout cornerTable;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);
fixedHeaderTableLayout = findViewById(R.id.FixedHeaderTableLayout);
pgsBar = findViewById(R.id.pBar);

// Really this should be done in the background as generating such a big layout takes time
GenerateTables generateTables = new GenerateTables(this);
generateTables.execute();


}

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);

// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Redraw screen calculating the new boundaries without new pan or scale
fixedHeaderTableLayout.calculatePanScale(0,0, 0, 0, 1f);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Redraw screen calculating the new boundaries without new pan or scale
fixedHeaderTableLayout.calculatePanScale(0,0, 0, 0, 1f);
}
}

@SuppressLint("StaticFieldLeak")
private class GenerateTables extends AsyncTask<Void, Integer, Void> {

private final SoftReference<MainActivity> activityReference;
private final Context mContext;

// only retain a soft reference to the activity
GenerateTables(MainActivity context) {
mContext = context;
activityReference = new SoftReference<>(context);
}

@Override
protected void onPreExecute() {
super.onPreExecute();

// get a reference to the activity if it is still there
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;

activity.pgsBar.setVisibility(View.VISIBLE);
}

@Override
protected Void doInBackground(Void... params) {
createTable(mContext);
return null;
}


@Override
protected void onPostExecute(Void param) {

// get a reference to the activity if it is still there
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) return;

// Setup FixHeader Table
fixedHeaderTableLayout.addViews(mainTable, columnHeaderTable, rowHeaderTable, cornerTable);

activity.pgsBar.setVisibility(View.GONE);
}

}


private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnm";

private static String getRandomString(int maxLength)
{
final Random random=new Random();
final int sizeOfRandomString = random.nextInt(maxLength);
final StringBuilder sb=new StringBuilder(sizeOfRandomString);
for(int i=0;i<sizeOfRandomString;++i)
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
return sb.toString();
// Buttons management
public void mainExample(View view) {
Intent intent = new Intent(this, MainExampleActivity.class);
startActivity(intent);
}

private void createTable(Context mContext){
// Create our 4 Sub Tables
mainTable = new FixedHeaderSubTableLayout(mContext);
// 25 x 5 in size
float textSize = 20.0f;
for (int i = 1; i <=25; i++) {
FixedHeaderTableRow tableRowData = new FixedHeaderTableRow(mContext);
// Add some data
for (int j = 1; j <= 25; j++) {
// Add a Textview
TextView textView = new TextView(mContext);
textView.setGravity(Gravity.CENTER);
textView.setText(String.format(Locale.ROOT,"C%d:R%d:%s", j, i, getRandomString(j)));
textView.setBackgroundResource(R.drawable.list_border);
textView.setPadding(5 ,5,5,5);
textView.setTextSize(textSize * 1.5f);
textView.setTextColor(getResources().getColor(R.color.colorText));
textView.setOnClickListener(v -> {
if (v.isSelected()){
v.setSelected(false);
v.setBackgroundResource(R.drawable.list_border);
} else {
v.setSelected(true);
v.setBackgroundResource(R.drawable.selected_border);
}
});
tableRowData.addView(textView);
}
mainTable.addView(tableRowData);
}

columnHeaderTable = new FixedHeaderSubTableLayout(mContext);
// 2 x 5 in size
for (int i = 1; i <= 2; i++) {
FixedHeaderTableRow tableRowData = new FixedHeaderTableRow(mContext);
// Add some data
for (int j = 1; j <= 25; j++) {
// Add a Textview
TextView textView = new TextView(mContext);
textView.setGravity(Gravity.CENTER);
textView.setText(String.format(Locale.ROOT,"C%d:%d", i, j));
textView.setBackgroundResource(R.drawable.list_border);
textView.setPadding(5 ,5,5,5);
textView.setTextSize(textSize);
textView.setTextColor(getResources().getColor(R.color.colorText));
textView.setOnClickListener(v -> {
if (v.isSelected()){
v.setSelected(false);
v.setBackgroundResource(R.drawable.list_border);
} else {
v.setSelected(true);
v.setBackgroundResource(R.drawable.selected_border);
}
});
tableRowData.addView(textView);
}
columnHeaderTable.addView(tableRowData);
}
columnHeaderTable.setBackgroundResource(R.drawable.bottom_border);

rowHeaderTable = new FixedHeaderSubTableLayout(mContext);
// 25 x 1 in size
for (int i = 1; i <= 25; i++) {
FixedHeaderTableRow tableRowData = new FixedHeaderTableRow(mContext);
// Add some data
for (int j = 1; j <= 1; j++) {
// Add a Textview
TextView textView = new TextView(mContext);
textView.setGravity(Gravity.CENTER);
textView.setText(String.format(Locale.ROOT,"R%d", i));
textView.setBackgroundResource(R.drawable.list_border);
textView.setPadding(5 ,5,5,5);
textView.setTextSize(textSize);
textView.setTextColor(getResources().getColor(R.color.colorText));
textView.setOnClickListener(v -> {
if (v.isSelected()){
v.setSelected(false);
v.setBackgroundResource(R.drawable.list_border);
} else {
v.setSelected(true);
v.setBackgroundResource(R.drawable.selected_border);
}
});
tableRowData.addView(textView);
}
rowHeaderTable.addView(tableRowData);
}
rowHeaderTable.setBackgroundResource(R.drawable.right_border);

cornerTable = new FixedHeaderSubTableLayout(mContext);
// 2 x 1 in size
for (int i = 1; i <= 2; i++) {
FixedHeaderTableRow tableRowData = new FixedHeaderTableRow(mContext);
// Add some data
for (int j = 1; j <= 1; j++) {
// Add a Textview
TextView textView = new TextView(mContext);
textView.setGravity(Gravity.CENTER);
textView.setText(String.format(Locale.ROOT,"A%d:%d",i , j));
textView.setBackgroundResource(R.drawable.list_border);
textView.setPadding(5 ,5,5,5);
textView.setTextSize(textSize * 1.5f);
textView.setTextColor(getResources().getColor(R.color.colorText));
textView.setOnClickListener(v -> {
if (v.isSelected()){
v.setSelected(false);
v.setBackgroundResource(R.drawable.list_border);
} else {
v.setSelected(true);
v.setBackgroundResource(R.drawable.selected_border);
}
});
tableRowData.addView(textView);
}
cornerTable.addView(tableRowData);
}
cornerTable.setBackgroundResource(R.drawable.corner_border);

fixedHeaderTableLayout.setMinScale(0.1f);
public void multiTableExample(View view) {
Intent intent = new Intent(this, MultiTableExampleActivity.class);
startActivity(intent);
}
}
Loading

0 comments on commit 2072405

Please sign in to comment.