Propper tables

Tables with headers and scrolls on edges
This commit is contained in:
Przemek Grondek 2014-07-25 15:02:05 +02:00
parent a9d877784f
commit f9f5266c0f
5 changed files with 168 additions and 58 deletions

View file

@ -0,0 +1,35 @@
package info.nerull7.mysqlbrowser;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
/**
* Created by nerull7 on 25.07.14.
*/
public class CustomScrollView extends ScrollView {
private OnScrollChangedListener listener;
public void setOnScrollChangedListener(OnScrollChangedListener listener){
this.listener = listener;
}
public CustomScrollView(Context context) {
super(context);
}
public CustomScrollView(Context context, AttributeSet attributeSet){
super(context,attributeSet);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
if(listener!=null)
listener.onScrollChanged(l,t,oldl,oldt);
}
public interface OnScrollChangedListener{
public void onScrollChanged(int l, int t, int oldl, int oldt);
}
}

View file

@ -26,7 +26,7 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
*/
public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener{
private TableLayout entriesTable;
private ScrollView entriesScrollView;
private CustomScrollView entriesScrollView;
private FrameLayout headerFrame;
private RelativeLayout rootView;
private TableRow.LayoutParams layoutParams;
@ -37,31 +37,56 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
private int entriesLimit;
private int page;
private ProgressBar progressBar;
private ScrollView fakeScrollView;
private View dummyView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_entries, container, false);
databaseName = getArguments().getString(Static.DATABASE_NAME_ARG);
tableName = getArguments().getString(Static.TABLE_NAME_ARG);
entriesTable = (TableLayout) rootView.findViewById(R.id.entriesTable);
entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView);
headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
entriesLimit = getActivity().getSharedPreferences(SettingsFragment.PREFERENCE_FILE, Context.MODE_PRIVATE).getInt(SettingsFragment.ENTRIES_PAGE_LIMIT, SettingsFragment.ENTRIES_PAGE_LIMIT_DEF);
this.rootView = (RelativeLayout) rootView;
page = getArguments().getInt(Static.PAGE_ARG);
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
initArguments();
initViewItems(rootView);
// setupActionBar();
headerRow = new TableRow(getActivity());
layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
Static.asyncDatabaseConnector.setListReturnListener(this);
Static.asyncDatabaseConnector.setMatrixReturnListener(this);
Static.asyncDatabaseConnector.getFields(tableName);
return rootView;
}
private void initArguments(){
databaseName = getArguments().getString(Static.DATABASE_NAME_ARG);
tableName = getArguments().getString(Static.TABLE_NAME_ARG);
page = getArguments().getInt(Static.PAGE_ARG);
entriesLimit = getActivity().getSharedPreferences(SettingsFragment.PREFERENCE_FILE, Context.MODE_PRIVATE).getInt(SettingsFragment.ENTRIES_PAGE_LIMIT, SettingsFragment.ENTRIES_PAGE_LIMIT_DEF);
}
private void initViewItems(View rootView){
headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
entriesTable = (TableLayout) rootView.findViewById(R.id.entriesTable);
entriesScrollView = (CustomScrollView) rootView.findViewById(R.id.entriesScrollView);
fakeScrollView = (ScrollView) rootView.findViewById(R.id.fakeScroll);
progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
dummyView = rootView.findViewById(R.id.dummyView);
this.rootView = (RelativeLayout) rootView;
entriesScrollView.setOnScrollChangedListener(new CustomScrollView.OnScrollChangedListener() {
@Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
fakeScrollView.scrollTo(0,t);
}
});
layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
headerFrame.setVisibility(View.INVISIBLE);
entriesTable.setVisibility(View.INVISIBLE);
}
// TODO Handling ActionBar
// private void setupActionBar() {
// ActionBar actionBar = getActivity().getActionBar();
// actionBar.
@ -82,7 +107,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
}
entriesTable.addView(newRow);
}
entriesTable.addView(headerRow);
} else {
TextView errorMessage = new TextView(getActivity());
errorMessage.setText(R.string.error_no_entries);
@ -90,15 +114,17 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
errorMessage.setClickable(false);
entriesScrollView.removeView(entriesTable);
rootView.addView(errorMessage);
headerFrame.addView(headerRow);
headerRow.setVisibility(View.VISIBLE);
}
syncWidths(); // please don't crash
fakeScroll();
progressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onListReturn(List<String> fieldList) { // TODO: Fix bug not showing header
public void onListReturn(List<String> fieldList) {
// First we need header
headerRow = new TableRow(getActivity());
headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
for(int i =0;i<fieldList.size();i++){
TextView textView = new TextView(getActivity());
@ -107,28 +133,50 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
textView.setLayoutParams(layoutParams);
headerRow.addView(textView);
}
headerRow.setVisibility(View.INVISIBLE);
headerFrame.addView(headerRow);
View fakeHeaderView = new View(getActivity()){
@Override
public void draw(Canvas canvas) {
headerRow.draw(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = headerRow.getMeasuredWidth();
int height = headerRow.getMeasuredHeight();
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
};
headerFrame.addView(fakeHeaderView);
Static.asyncDatabaseConnector.setMatrixReturnListener(this);
Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page);
}
private void syncWidths(){ // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
TableRow headerRow = (TableRow) headerFrame.getChildAt(0);
int maxWidth[]= new int[headerRow.getChildCount()];
for(int i=0;i<headerRow.getChildCount();i++){
TextView textView = (TextView) headerRow.getChildAt(i);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
maxWidth[i] = textView.getMeasuredWidth();
}
for(int i=0;i<entriesTable.getChildCount();i++){
TableRow tableRow = (TableRow) entriesTable.getChildAt(i);
for(int j=0;j<tableRow.getChildCount();j++){
TextView textView = (TextView) tableRow.getChildAt(j);
textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = textView.getMeasuredWidth();
if(width>maxWidth[j])
maxWidth[j]=width;
}
}
for(int i=0;i<headerRow.getChildCount();i++){
TableRow entriesRow = (TableRow) entriesTable.getChildAt(0);
TextView tmpEntries = (TextView) entriesRow.getChildAt(i);
TextView tmpHeader = (TextView) headerRow.getChildAt(i);
tmpEntries.setWidth(maxWidth[i]);
tmpHeader.setWidth(maxWidth[i]);
}
headerFrame.setVisibility(View.VISIBLE);
entriesTable.setVisibility(View.VISIBLE);
}
private void fakeScroll(){
entriesScrollView.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
int height = entriesScrollView.getMeasuredHeight();
dummyView.setMinimumHeight(height);
}
}

View file

@ -4,6 +4,8 @@
android:layout_height="match_parent"
tools:context="info.nerull7.mysqlbrowser.EntriesFragment">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="true"
@ -14,29 +16,48 @@
android:layout_alignParentTop="false"
android:layout_marginTop="-7dp" />
<FrameLayout
android:layout_width="match_parent"
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/headerFrame"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"></FrameLayout>
android:id="@+id/horizontalScrollView" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/container">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/headerFrame"
android:paddingTop="@dimen/activity_vertical_margin"></FrameLayout>
<info.nerull7.mysqlbrowser.CustomScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/entriesScrollView"
android:layout_below="@+id/headerFrame"
android:scrollbars="none">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/entriesTable">
</TableLayout>
</info.nerull7.mysqlbrowser.CustomScrollView>
</RelativeLayout>
</HorizontalScrollView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/entriesScrollView"
android:layout_below="@+id/headerFrame"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin">
<TableLayout
android:layout_width="@dimen/activity_horizontal_margin"
android:layout_height="fill_parent"
android:layout_below="@+id/loginProgressBar"
android:layout_alignParentRight="true"
android:foregroundGravity="right"
android:id="@+id/fakeScroll">
<View
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/entriesTable">
</TableLayout>
android:id="@+id/dummyView"/>
</ScrollView>
</RelativeLayout>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomScrollView">
</declare-styleable>
</resources>

View file

@ -1,6 +1,6 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="activity_horizontal_margin">5dp</dimen>
<dimen name="activity_vertical_margin">5dp</dimen>
<dimen name="login_text_layout_width">50dp</dimen>
</resources>