extends AdaptiveTableDataSetObserver {
13 | /**
14 | * @return Item click listener
15 | */
16 | @Nullable
17 | OnItemClickListener getOnItemClickListener();
18 |
19 | /**
20 | * Set new item click listener
21 | *
22 | * @param onItemClickListener new item click listener
23 | */
24 | void setOnItemClickListener(@Nullable OnItemClickListener onItemClickListener);
25 |
26 | /**
27 | * @return Item long click listener
28 | */
29 | @Nullable
30 | OnItemLongClickListener getOnItemLongClickListener();
31 |
32 | /**
33 | * Set new item long click listener
34 | *
35 | * @param onItemLongClickListener new item long click listener
36 | */
37 | void setOnItemLongClickListener(@Nullable OnItemLongClickListener onItemLongClickListener);
38 |
39 | /**
40 | * Register an observer that is called when changes happen to the data used
41 | * by this adapter.
42 | *
43 | * @param observer the object that gets notified when the data set changes.
44 | */
45 | void registerDataSetObserver(@NonNull AdaptiveTableDataSetObserver observer);
46 |
47 | /**
48 | * Unregister an observer that has previously been registered with this
49 | * adapter via {@link #registerDataSetObserver}.
50 | *
51 | * @param observer the object to unregister.
52 | */
53 | void unregisterDataSetObserver(@NonNull AdaptiveTableDataSetObserver observer);
54 |
55 |
56 | /**
57 | * How many rows are in the data table represented by this Adapter.
58 | *
59 | * @return count of rows with header
60 | */
61 | int getRowCount();
62 |
63 | /**
64 | * How many columns are in the data table represented by this Adapter.
65 | *
66 | * @return count of columns with header
67 | */
68 | int getColumnCount();
69 |
70 | /**
71 | * Called when {@link AdaptiveTableLayout} needs a new ITEM {@link ViewHolder}
72 | *
73 | * @param parent The ViewGroup into which the new View will be added after it is bound to
74 | * an adapter position.
75 | * @return A new ViewHolder that holds a View of the given view type.
76 | * @see #onBindViewHolder(ViewHolder, int, int)
77 | */
78 | @NonNull
79 | VH onCreateItemViewHolder(@NonNull ViewGroup parent);
80 |
81 | /**
82 | * Called when {@link AdaptiveTableLayout} needs a new COLUMN HEADER ITEM {@link ViewHolder}
83 | *
84 | * @param parent The ViewGroup into which the new View will be added after it is bound to
85 | * an adapter position.
86 | * @return A new ViewHolder that holds a View of the given view type.
87 | * @see #onBindHeaderColumnViewHolder(ViewHolder, int)
88 | */
89 | @NonNull
90 | VH onCreateColumnHeaderViewHolder(@NonNull ViewGroup parent);
91 |
92 | /**
93 | * Called when {@link AdaptiveTableLayout} needs a new ROW HEADER ITEM {@link ViewHolder}
94 | *
95 | * @param parent The ViewGroup into which the new View will be added after it is bound to
96 | * an adapter position.
97 | * @return A new ViewHolder that holds a View of the given view type.
98 | * @see #onBindHeaderRowViewHolder(ViewHolder, int)
99 | */
100 | @NonNull
101 | VH onCreateRowHeaderViewHolder(@NonNull ViewGroup parent);
102 |
103 | /**
104 | * Called when {@link AdaptiveTableLayout} needs a new LEFT TOP HEADER ITEM {@link ViewHolder}
105 | *
106 | * @param parent The ViewGroup into which the new View will be added after it is bound to
107 | * an adapter position.
108 | * @return A new ViewHolder that holds a View of the given view type.
109 | * @see #onBindLeftTopHeaderViewHolder(ViewHolder)
110 | */
111 | @NonNull
112 | VH onCreateLeftTopHeaderViewHolder(@NonNull ViewGroup parent);
113 |
114 |
115 | /**
116 | * Called by {@link AdaptiveTableLayout} to display the data at the specified position. This method should
117 | * update the contents of the {@link ViewHolder#getItemView()} to reflect the item at the given
118 | * position.
119 | *
120 | * @param viewHolder The ITEM {@link ViewHolder} which should be updated to represent the contents of the
121 | * item at the given position in the data set.
122 | * @param row The row index of the item within the adapter's data set.
123 | * @param column The column index of the item within the adapter's data set.
124 | */
125 | void onBindViewHolder(@NonNull VH viewHolder, int row, int column);
126 |
127 | /**
128 | * Called by {@link AdaptiveTableLayout} to display the data at the specified position. This method should
129 | * update the contents of the {@link ViewHolder#getItemView()} to reflect the item at the given
130 | * position.
131 | *
132 | * @param viewHolder The COLUMN HEADER ITEM {@link ViewHolder} which should be updated to represent the contents of the
133 | * item at the given position in the data set.
134 | * @param column The column index of the item within the adapter's data set.
135 | */
136 | void onBindHeaderColumnViewHolder(@NonNull VH viewHolder, int column);
137 |
138 | /**
139 | * Called by {@link AdaptiveTableLayout} to display the data at the specified position. This method should
140 | * update the contents of the {@link ViewHolder#getItemView()} to reflect the item at the given
141 | * position.
142 | *
143 | * @param viewHolder The ROW HEADER ITEM {@link ViewHolder} which should be updated to represent the contents of the
144 | * item at the given position in the data set.
145 | * @param row The row index of the item within the adapter's data set.
146 | */
147 | void onBindHeaderRowViewHolder(@NonNull VH viewHolder, int row);
148 |
149 | /**
150 | * Called by {@link AdaptiveTableLayout} to display the data at the specified position. This method should
151 | * update the contents of the {@link ViewHolder#getItemView()} to reflect the item at the given
152 | * position.
153 | *
154 | * @param viewHolder The TOP LEFT HEADER ITEM{@link ViewHolder} which should be updated to represent the contents of the
155 | * item at the given position in the data set.
156 | */
157 | void onBindLeftTopHeaderViewHolder(@NonNull VH viewHolder);
158 |
159 |
160 | /**
161 | * Return the width of the column.
162 | *
163 | * @param column the column index.
164 | * @return The width of the column, in pixels.
165 | */
166 | int getColumnWidth(int column);
167 |
168 |
169 | /**
170 | * Return the header column height.
171 | *
172 | * @return The header height of the columns, in pixels.
173 | */
174 | int getHeaderColumnHeight();
175 |
176 | /**
177 | * Return the height of the row.
178 | *
179 | * @param row the row index.
180 | * @return The height of the row, in pixels.
181 | */
182 | int getRowHeight(int row);
183 |
184 | /**
185 | * Return the header row width.
186 | *
187 | * @return The header width of the rows, in pixels.
188 | */
189 | int getHeaderRowWidth();
190 |
191 | /**
192 | * Called when a view created by this adapter has been recycled.
193 | *
194 | *
A view is recycled when a {@link AdaptiveTableLayout} decides that it no longer
195 | * needs to be attached. This can be because it has
196 | * fallen out of visibility or a set of cached views represented by views still
197 | * attached to the parent RecyclerView. If an item view has large or expensive data
198 | * bound to it such as large bitmaps, this may be a good place to release those
199 | * resources.
200 | *
201 | * {@link AdaptiveTableLayout} calls this method right before clearing ViewHolder's internal data and
202 | * sending it to Recycler.
203 | *
204 | * @param viewHolder The {@link ViewHolder} for the view being recycled
205 | */
206 | void onViewHolderRecycled(@NonNull VH viewHolder);
207 |
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/AdaptiveTableDataSetObserver.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | interface AdaptiveTableDataSetObserver {
4 | /**
5 | * Notify any registered observers that the data set has changed.
6 | * If you change the size of the data set, you must call {@link AdaptiveTableDataSetObserver#notifyLayoutChanged()} instead
7 | */
8 | void notifyDataSetChanged();
9 |
10 | /**
11 | * You must call this when something has changed which has invalidated the layout of this view
12 | * or the size of the data set was changed
13 | */
14 | void notifyLayoutChanged();
15 |
16 | /**
17 | * Notify any registered observers that the item at
18 | * (rowIndex
;columnIndex
) has changed.
19 | *
20 | * @param rowIndex the row index
21 | * @param columnIndex the column index
22 | */
23 | void notifyItemChanged(int rowIndex, int columnIndex);
24 |
25 | /**
26 | * Notify any registered observers that the row with rowIndex has changed.
27 | *
28 | * @param rowIndex the row index
29 | */
30 | void notifyRowChanged(int rowIndex);
31 |
32 | /**
33 | * Notify any registered observers that the column with columnIndex has changed.
34 | *
35 | * @param columnIndex the column index
36 | */
37 | void notifyColumnChanged(int columnIndex);
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/AdaptiveTableLayoutSettings.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | /**
4 | * Settings keeper class.
5 | */
6 | class AdaptiveTableLayoutSettings {
7 |
8 | /**
9 | * Layout width
10 | */
11 | private int mLayoutWidth;
12 | /**
13 | * Layout height
14 | */
15 | private int mLayoutHeight;
16 |
17 | private boolean mIsHeaderFixed;
18 |
19 | private int mCellMargin;
20 |
21 | /**
22 | * if true - value of row header fixed to the row. Fixed to the data
23 | * if false - fixed to the number of row. Fixed to the row' number from 0 to n.
24 | */
25 | private boolean mSolidRowHeader;
26 |
27 | /**
28 | * If true, then the table can be edited, otherwise it is impossible
29 | */
30 | private boolean mDragAndDropEnabled;
31 |
32 |
33 | AdaptiveTableLayoutSettings() {
34 | }
35 |
36 | int getLayoutWidth() {
37 | return mLayoutWidth;
38 | }
39 |
40 | AdaptiveTableLayoutSettings setLayoutWidth(int layoutWidth) {
41 | mLayoutWidth = layoutWidth;
42 | return this;
43 | }
44 |
45 | int getLayoutHeight() {
46 | return mLayoutHeight;
47 | }
48 |
49 | AdaptiveTableLayoutSettings setLayoutHeight(int layoutHeight) {
50 | mLayoutHeight = layoutHeight;
51 | return this;
52 | }
53 |
54 | public boolean isHeaderFixed() {
55 | return mIsHeaderFixed;
56 | }
57 |
58 | public AdaptiveTableLayoutSettings setHeaderFixed(boolean headerFixed) {
59 | mIsHeaderFixed = headerFixed;
60 | return this;
61 | }
62 |
63 | public int getCellMargin() {
64 | return mCellMargin;
65 | }
66 |
67 | public AdaptiveTableLayoutSettings setCellMargin(int cellMargin) {
68 | mCellMargin = cellMargin;
69 | return this;
70 | }
71 |
72 | public boolean isSolidRowHeader() {
73 | return mSolidRowHeader;
74 | }
75 |
76 | public AdaptiveTableLayoutSettings setSolidRowHeader(boolean solidRowHeader) {
77 | mSolidRowHeader = solidRowHeader;
78 | return this;
79 | }
80 |
81 | public boolean isDragAndDropEnabled() {
82 | return mDragAndDropEnabled;
83 | }
84 |
85 | public void setDragAndDropEnabled(boolean dragAndDropEnabled) {
86 | mDragAndDropEnabled = dragAndDropEnabled;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/AdaptiveTableManagerRTL.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.annotation.TargetApi;
4 | import android.os.Build;
5 |
6 | /**
7 | * same as {@link AdaptiveTableManager}, but support rtl direction
8 | */
9 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
10 | class AdaptiveTableManagerRTL extends AdaptiveTableManager {
11 |
12 | private LayoutDirectionHelper mLayoutDirectionHelper;
13 |
14 | AdaptiveTableManagerRTL(LayoutDirectionHelper layoutDirectionHelper) {
15 | mLayoutDirectionHelper = layoutDirectionHelper;
16 | }
17 |
18 | @Override
19 | int getColumnByXWithShift(int x, int shiftEveryStep) {
20 | if (!mLayoutDirectionHelper.isRTL()) {
21 | return super.getColumnByXWithShift(x, shiftEveryStep);
22 | } else {
23 | checkForInit();
24 | int sum = 0;
25 | if (x <= sum) {
26 | return 0;
27 | }
28 | for (int count = getColumnWidths().length, i = 0; i < count; i++) {
29 | int nextSum = sum + getColumnWidths()[i] + shiftEveryStep;
30 | if (x > sum && x < nextSum) {
31 | return i;
32 | } else if (x < nextSum) {
33 | return i - 1;
34 | }
35 | sum = nextSum;
36 | }
37 | return getColumnWidths().length - 1;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/AdaptiveTableState.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | /**
4 | * Layout state holder.
5 | */
6 | class AdaptiveTableState {
7 |
8 | static final int NO_DRAGGING_POSITION = -1;
9 | /**
10 | * Current scroll position.
11 | */
12 | private int mScrollX;
13 | private int mScrollY;
14 |
15 | /**
16 | * Dragging row flag
17 | */
18 | private boolean mIsRowDragging;
19 |
20 | /**
21 | * Dragging column flag
22 | */
23 | private boolean mIsColumnDragging;
24 |
25 | /**
26 | * Dragging column index
27 | */
28 | private int mColumnDraggingIndex;
29 | /**
30 | * Dragging row index
31 | */
32 | private int mRowDraggingIndex;
33 |
34 |
35 | int getScrollX() {
36 | return mScrollX;
37 | }
38 |
39 | void setScrollX(int scrollX) {
40 | mScrollX = scrollX;
41 | }
42 |
43 | int getScrollY() {
44 | return mScrollY;
45 | }
46 |
47 | void setScrollY(int scrollY) {
48 | mScrollY = scrollY;
49 | }
50 |
51 | boolean isRowDragging() {
52 | return mIsRowDragging;
53 | }
54 |
55 | void setRowDragging(boolean rowDragging, int rowIndex) {
56 | mIsRowDragging = rowDragging;
57 | mRowDraggingIndex = rowIndex;
58 | }
59 |
60 | boolean isColumnDragging() {
61 | return mIsColumnDragging;
62 | }
63 |
64 | void setColumnDragging(boolean columnDragging, int columnIndex) {
65 | mIsColumnDragging = columnDragging;
66 | mColumnDraggingIndex = columnIndex;
67 | }
68 |
69 | boolean isDragging() {
70 | return mIsColumnDragging || mIsRowDragging;
71 | }
72 |
73 | int getColumnDraggingIndex() {
74 | return mColumnDraggingIndex;
75 | }
76 |
77 | int getRowDraggingIndex() {
78 | return mRowDraggingIndex;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/BaseDataAdaptiveTableLayoutAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | public abstract class BaseDataAdaptiveTableLayoutAdapter extends LinkedAdaptiveTableAdapter implements
4 | DataAdaptiveTableLayoutAdapter {
5 |
6 | /**
7 | * @return data matrix
8 | */
9 | protected abstract Object[][] getItems();
10 |
11 | /**
12 | * @return row's headers array
13 | */
14 | protected abstract Object[] getRowHeaders();
15 |
16 | /**
17 | * @return column's headers array
18 | */
19 | protected abstract Object[] getColumnHeaders();
20 |
21 | @Override
22 | public void changeColumns(int columnIndex, int columnToIndex) {
23 | // switch data
24 | switchTwoColumns(columnIndex, columnToIndex);
25 | // switch headers
26 | switchTwoColumnHeaders(columnIndex, columnToIndex);
27 | }
28 |
29 | /**
30 | * Switch 2 columns with data
31 | *
32 | * @param columnIndex column from
33 | * @param columnToIndex column to
34 | */
35 | void switchTwoColumns(int columnIndex, int columnToIndex) {
36 | for (int i = 0; i < getRowCount() - 1; i++) {
37 | Object cellData = getItems()[i][columnToIndex];
38 | getItems()[i][columnToIndex] = getItems()[i][columnIndex];
39 | getItems()[i][columnIndex] = cellData;
40 | }
41 | }
42 |
43 | /**
44 | * Switch 2 columns headers with data
45 | *
46 | * @param columnIndex column header from
47 | * @param columnToIndex column header to
48 | */
49 | void switchTwoColumnHeaders(int columnIndex, int columnToIndex) {
50 | Object cellData = getColumnHeaders()[columnToIndex];
51 | getColumnHeaders()[columnToIndex] = getColumnHeaders()[columnIndex];
52 | getColumnHeaders()[columnIndex] = cellData;
53 | }
54 |
55 | @Override
56 | public void changeRows(int rowIndex, int rowToIndex, boolean solidRowHeader) {
57 | // switch data
58 | switchTwoRows(rowIndex, rowToIndex);
59 | if (solidRowHeader) {
60 | // switch headers
61 | switchTwoRowHeaders(rowIndex, rowToIndex);
62 | }
63 | }
64 |
65 | /**
66 | * Switch 2 rows with data
67 | *
68 | * @param rowIndex row from
69 | * @param rowToIndex row to
70 | */
71 | void switchTwoRows(int rowIndex, int rowToIndex) {
72 | for (int i = 0; i < getItems().length; i++) {
73 | Object cellData = getItems()[rowToIndex][i];
74 | getItems()[rowToIndex][i] = getItems()[rowIndex][i];
75 | getItems()[rowIndex][i] = cellData;
76 | }
77 | }
78 |
79 | /**
80 | * Switch 2 rows headers with data
81 | *
82 | * @param rowIndex row header from
83 | * @param rowToIndex row header to
84 | */
85 | void switchTwoRowHeaders(int rowIndex, int rowToIndex) {
86 | Object cellData = getRowHeaders()[rowToIndex];
87 | getRowHeaders()[rowToIndex] = getRowHeaders()[rowIndex];
88 | getRowHeaders()[rowIndex] = cellData;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/DataAdaptiveTableLayoutAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 |
6 | interface DataAdaptiveTableLayoutAdapter extends AdaptiveTableAdapter {
7 | /**
8 | * Method calls when need to need to switch 2 columns with each other in the data matrix
9 | *
10 | * @param columnIndex column from
11 | * @param columnToIndex column to
12 | */
13 | void changeColumns(int columnIndex, int columnToIndex);
14 |
15 | /**
16 | * Method calls when need to need to switch 2 rows with each other in the data matrix
17 | *
18 | * @param rowIndex row from
19 | * @param rowToIndex row to
20 | * @param solidRowHeader fixed to the data or to the row number.
21 | */
22 | void changeRows(int rowIndex, int rowToIndex, boolean solidRowHeader);
23 |
24 | void onSaveInstanceState(@NonNull Bundle bundle);
25 |
26 | void onRestoreInstanceState(@NonNull Bundle bundle);
27 | }
28 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/DataSetObserverProxy.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | class DataSetObserverProxy implements AdaptiveTableDataSetObserver {
4 | private final AdaptiveTableAdapter mAdaptiveTableAdapter;
5 |
6 | DataSetObserverProxy(AdaptiveTableAdapter adaptiveTableAdapter) {
7 | mAdaptiveTableAdapter = adaptiveTableAdapter;
8 | }
9 |
10 | @Override
11 | public void notifyDataSetChanged() {
12 | mAdaptiveTableAdapter.notifyDataSetChanged();
13 | }
14 |
15 | @Override
16 | public void notifyLayoutChanged() {
17 | mAdaptiveTableAdapter.notifyLayoutChanged();
18 | }
19 |
20 | @Override
21 | public void notifyItemChanged(int rowIndex, int columnIndex) {
22 | mAdaptiveTableAdapter.notifyItemChanged(rowIndex, columnIndex);
23 | }
24 |
25 | @Override
26 | public void notifyRowChanged(int rowIndex) {
27 | mAdaptiveTableAdapter.notifyRowChanged(rowIndex);
28 | }
29 |
30 | @Override
31 | public void notifyColumnChanged(int columnIndex) {
32 | mAdaptiveTableAdapter.notifyColumnChanged(columnIndex);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/DragAndDropPoints.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.graphics.Point;
4 |
5 | /**
6 | * Helps implement dragging feature.
7 | * Contains start, offset and end point in drag and drop mode.
8 | */
9 | class DragAndDropPoints {
10 | /**
11 | * Start dragging touch point
12 | */
13 | private final Point mStart;
14 | /**
15 | * Screen offset (touch position)
16 | */
17 | private final Point mOffset;
18 |
19 | /**
20 | * End dragging touch point
21 | */
22 | private final Point mEnd;
23 |
24 | DragAndDropPoints() {
25 | mStart = new Point();
26 | mOffset = new Point();
27 | mEnd = new Point();
28 | }
29 |
30 | Point getStart() {
31 | return mStart;
32 | }
33 |
34 | Point getOffset() {
35 | return mOffset;
36 | }
37 |
38 | Point getEnd() {
39 | return mEnd;
40 | }
41 |
42 | void setStart(int x, int y) {
43 | mStart.set(x, y);
44 | }
45 |
46 | void setOffset(int x, int y) {
47 | mOffset.set(x, y);
48 | }
49 |
50 | void setEnd(int x, int y) {
51 | mEnd.set(x, y);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/DragAndDropScrollRunnable.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Move table layout logic in dragging mode
7 | */
8 | class DragAndDropScrollRunnable implements Runnable {
9 | private View mView;
10 | private boolean isFinished;
11 |
12 | private int mDiffX;
13 | private int mDiffY;
14 |
15 | DragAndDropScrollRunnable(View view) {
16 | mView = view;
17 | isFinished = true;
18 | }
19 |
20 | synchronized void touch(int touchX, int touchY, @ScrollType int orientation) {
21 |
22 | int partOfWidth = mView.getWidth() / 4;
23 | // vertical scroll area (top, bottom)
24 | int partOfHeight = mView.getHeight() / 4;
25 |
26 |
27 | if (orientation == ScrollType.SCROLL_HORIZONTAL) {
28 | if (touchX < partOfWidth) {
29 | // if touch in left horizontal area -> scroll to left
30 | start(touchX - partOfWidth, 0);
31 | } else if (touchX > mView.getWidth() - partOfWidth) {
32 | // if touch in right horizontal area -> scroll to right
33 | start(touchX - mView.getWidth() + partOfWidth, 0);
34 | } else {
35 | // touch between scroll left and right areas.
36 | mDiffX = 0;
37 | mDiffY = 0;
38 | }
39 | } else if (orientation == ScrollType.SCROLL_VERTICAL) {
40 | if (touchY < partOfHeight) {
41 | // if touch in top vertical area -> scroll to top
42 | start(0, touchY - partOfHeight);
43 | } else if (touchY > mView.getHeight() - partOfHeight) {
44 | // if touch in bottom vertical area -> scroll to bottom
45 | start(0, touchY - mView.getHeight() + partOfHeight);
46 | } else {
47 | // touch between scroll top and bottom areas.
48 | mDiffX = 0;
49 | mDiffY = 0;
50 | }
51 | }
52 | }
53 |
54 | private synchronized void start(int diffX, int diffY) {
55 | // save start data
56 | mDiffX = diffX;
57 | mDiffY = diffY;
58 | // check if scrolling in the process
59 | if (isFinished) {
60 | // start scroll
61 | isFinished = false;
62 | mView.post(this);
63 | }
64 | }
65 |
66 | @Override
67 | public void run() {
68 | // scroll speed. Calculated by hand.
69 | int shiftDistanceX = mDiffX / 5;
70 | int shiftDistanceY = mDiffY / 5;
71 |
72 | if ((shiftDistanceX != 0 || shiftDistanceY != 0) && !isFinished) {
73 | // change state
74 | isFinished = false;
75 | // scroll view
76 | mView.scrollBy(shiftDistanceX, shiftDistanceY);
77 | // start self again
78 | mView.post(this);
79 | } else {
80 | // have no shift distance or need to finish.
81 | stop();
82 | }
83 | }
84 |
85 | synchronized void stop() {
86 | // vars to default
87 | mDiffX = 0;
88 | mDiffY = 0;
89 |
90 | // change state
91 | isFinished = true;
92 |
93 | // remove callbacks
94 | mView.removeCallbacks(this);
95 | }
96 |
97 | boolean isFinished() {
98 | return isFinished;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/LayoutDirection.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | @IntDef({
9 | LayoutDirection.LTR,
10 | LayoutDirection.RTL
11 | })
12 | /**
13 | * Type of layout directions. Same values as in android.util.LayoutDirection
14 | * This interface needed because project min API is 16
15 | */
16 | @Retention(RetentionPolicy.SOURCE)
17 | @interface LayoutDirection {
18 | /**
19 | * Top left header
20 | */
21 | int LTR = 0;
22 | /**
23 | * Vertical header
24 | */
25 | int RTL = 1;
26 | }
27 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/LayoutDirectionHelper.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | /**
4 | * Helper for convenient work with layout direction
5 | */
6 | class LayoutDirectionHelper {
7 | private int mLayoutDirection;
8 |
9 | LayoutDirectionHelper(int direction) {
10 | mLayoutDirection = direction;
11 | }
12 |
13 | private int getLayoutDirection() {
14 | return mLayoutDirection;
15 | }
16 |
17 | void setLayoutDirection(int direction) {
18 | mLayoutDirection = direction;
19 | }
20 |
21 | boolean isRTL() {
22 | return getLayoutDirection() == LayoutDirection.RTL;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/LinkedAdaptiveTableAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * {@inheritDoc}
11 | * Common base class of common implementation for an {@link AdaptiveTableAdapter} that
12 | * can be used in {@link AdaptiveTableLayout}.
13 | */
14 | public abstract class LinkedAdaptiveTableAdapter implements AdaptiveTableAdapter {
15 | protected boolean mIsRtl;
16 | /**
17 | * Set with observers
18 | */
19 | @NonNull
20 | private final List mAdaptiveTableDataSetObservers = new ArrayList<>();
21 |
22 | /**
23 | * Need to throw item click action
24 | */
25 | @Nullable
26 | private OnItemClickListener mOnItemClickListener;
27 |
28 | /**
29 | * Need to throw long item click action
30 | */
31 | @Nullable
32 | private OnItemLongClickListener mOnItemLongClickListener;
33 |
34 | @Override
35 | @Nullable
36 | public OnItemClickListener getOnItemClickListener() {
37 | return mOnItemClickListener;
38 | }
39 |
40 | @Override
41 | public void setOnItemClickListener(@Nullable OnItemClickListener onItemClickListener) {
42 | mOnItemClickListener = onItemClickListener;
43 | }
44 |
45 | @Override
46 | @Nullable
47 | public OnItemLongClickListener getOnItemLongClickListener() {
48 | return mOnItemLongClickListener;
49 | }
50 |
51 | @Override
52 | public void setOnItemLongClickListener(@Nullable OnItemLongClickListener onItemLongClickListener) {
53 | mOnItemLongClickListener = onItemLongClickListener;
54 | }
55 |
56 | @NonNull
57 | public List getAdaptiveTableDataSetObservers() {
58 | return mAdaptiveTableDataSetObservers;
59 | }
60 |
61 | /**
62 | * {@inheritDoc}
63 | *
64 | * @param observer the object that gets notified when the data set changes.
65 | */
66 | @Override
67 | public void registerDataSetObserver(@NonNull AdaptiveTableDataSetObserver observer) {
68 | mAdaptiveTableDataSetObservers.add(observer);
69 | }
70 |
71 | /**
72 | * {@inheritDoc}
73 | *
74 | * @param observer the object to unregister.
75 | */
76 | @Override
77 | public void unregisterDataSetObserver(@NonNull AdaptiveTableDataSetObserver observer) {
78 | mAdaptiveTableDataSetObservers.remove(observer);
79 | }
80 |
81 | /**
82 | * {@inheritDoc}
83 | */
84 | @Override
85 | public void notifyDataSetChanged() {
86 | for (AdaptiveTableDataSetObserver observer : mAdaptiveTableDataSetObservers) {
87 | observer.notifyDataSetChanged();
88 | }
89 | }
90 |
91 | /**
92 | * {@inheritDoc}
93 | *
94 | * @param rowIndex the row index
95 | * @param columnIndex the column index
96 | */
97 | @Override
98 | public void notifyItemChanged(int rowIndex, int columnIndex) {
99 | for (AdaptiveTableDataSetObserver observer : mAdaptiveTableDataSetObservers) {
100 | observer.notifyItemChanged(rowIndex, columnIndex);
101 | }
102 | }
103 |
104 | /**
105 | * {@inheritDoc}
106 | *
107 | * @param rowIndex the row index
108 | */
109 | @Override
110 | public void notifyRowChanged(int rowIndex) {
111 | for (AdaptiveTableDataSetObserver observer : mAdaptiveTableDataSetObservers) {
112 | observer.notifyRowChanged(rowIndex);
113 | }
114 | }
115 |
116 | /**
117 | * {@inheritDoc}
118 | *
119 | * @param columnIndex the column index
120 | */
121 | @Override
122 | public void notifyColumnChanged(int columnIndex) {
123 | for (AdaptiveTableDataSetObserver observer : mAdaptiveTableDataSetObservers) {
124 | observer.notifyColumnChanged(columnIndex);
125 | }
126 | }
127 |
128 | /**
129 | * {@inheritDoc}
130 | */
131 | @Override
132 | public void notifyLayoutChanged() {
133 | for (AdaptiveTableDataSetObserver observer : mAdaptiveTableDataSetObservers) {
134 | observer.notifyLayoutChanged();
135 | }
136 | }
137 |
138 | @Override
139 | public void onViewHolderRecycled(@NonNull VH viewHolder) {
140 | //do something
141 | }
142 |
143 | public boolean isRtl() {
144 | return mIsRtl;
145 | }
146 |
147 | public void setRtl(boolean rtl) {
148 | mIsRtl = rtl;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/OnItemClickListener.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | public interface OnItemClickListener {
4 | /**
5 | * Click item callback.
6 | *
7 | * @param row clicked item row
8 | * @param column clicked item column
9 | */
10 | void onItemClick(int row, int column);
11 |
12 | /**
13 | * Click row header item callback
14 | *
15 | * @param row clicked row header
16 | */
17 | void onRowHeaderClick(int row);
18 |
19 | /**
20 | * Click column header item callback
21 | *
22 | * @param column clicked column header
23 | */
24 | void onColumnHeaderClick(int column);
25 |
26 |
27 | /**
28 | * Click left top item callback
29 | */
30 | void onLeftTopHeaderClick();
31 | }
32 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/OnItemLongClickListener.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | public interface OnItemLongClickListener {
4 | /**
5 | * Long click item callback.
6 | *
7 | * @param row clicked item row
8 | * @param column clicked item column
9 | */
10 | void onItemLongClick(int row, int column);
11 |
12 | /**
13 | * Long click left top item callback
14 | */
15 | void onLeftTopHeaderLongClick();
16 | }
17 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/Recycler.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.util.SparseArray;
6 |
7 | import java.util.ArrayDeque;
8 | import java.util.Deque;
9 |
10 | /**
11 | * The Recycler facilitates reuse of mViewHolders across layouts.
12 | */
13 | class Recycler {
14 |
15 | private SparseArray> mViewHolders;
16 |
17 | /**
18 | * Constructor
19 | */
20 | @SuppressWarnings("unchecked")
21 | Recycler() {
22 | mViewHolders = new SparseArray<>(3);
23 | }
24 |
25 | /**
26 | * Add a view to the Recycler. This view may be reused in the function
27 | * {@link #popRecycledViewHolder(int)}
28 | *
29 | * @param viewHolder A viewHolder to add to the Recycler. It can no longer be used.
30 | */
31 | void pushRecycledView(@NonNull ViewHolder viewHolder) {
32 | Deque deque = mViewHolders.get(viewHolder.getItemType());
33 | if (deque == null) {
34 | deque = new ArrayDeque<>();
35 | mViewHolders.put(viewHolder.getItemType(), deque);
36 | }
37 | deque.push(viewHolder);
38 | }
39 |
40 | /**
41 | * Returns, if exists, a view of the type typeView
.
42 | *
43 | * @param itemType the type of view that you want.
44 | * @return a viewHolder of the type typeView
. null
if
45 | * not found.
46 | */
47 | @Nullable
48 | ViewHolder popRecycledViewHolder(int itemType) {
49 | Deque deque = mViewHolders.get(itemType);
50 | return deque == null || deque.isEmpty() ? null : deque.pop();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ScrollHelper.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.view.GestureDetectorCompat;
6 | import android.view.GestureDetector;
7 | import android.view.MotionEvent;
8 |
9 |
10 | class ScrollHelper implements GestureDetector.OnGestureListener {
11 | /**
12 | * Gesture detector -> Scroll, Fling, Tap, LongPress, ...
13 | * Using when user need to scroll table
14 | */
15 | private final GestureDetectorCompat mGestureDetectorCompat;
16 |
17 | @Nullable
18 | private ScrollHelperListener mListener;
19 |
20 | ScrollHelper(Context context) {
21 | mGestureDetectorCompat = new GestureDetectorCompat(context, this);
22 | mGestureDetectorCompat.setIsLongpressEnabled(true);
23 | }
24 |
25 | void setListener(@Nullable ScrollHelperListener listener) {
26 | mListener = listener;
27 | }
28 |
29 | @Override
30 | public boolean onDown(MotionEvent e) {
31 | // catch down action
32 | return mListener == null || mListener.onDown(e);
33 | }
34 |
35 | @Override
36 | public void onShowPress(MotionEvent e) {
37 | // nothing to do
38 | }
39 |
40 | @Override
41 | public boolean onSingleTapUp(MotionEvent e) {
42 | // catch click action
43 | return mListener != null && mListener.onSingleTapUp(e);
44 | }
45 |
46 | @Override
47 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
48 | // catch scroll action
49 | return mListener != null && mListener.onScroll(e1, e2, distanceX, distanceY);
50 | }
51 |
52 | @Override
53 | public void onLongPress(MotionEvent e) {
54 | // catch long click action
55 | if (mListener != null) {
56 | mListener.onLongPress(e);
57 | }
58 | }
59 |
60 | @Override
61 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
62 | // catch fling action
63 | return mListener == null || mListener.onFling(e1, e2, velocityX, velocityY);
64 | }
65 |
66 | boolean onTouch(MotionEvent event) {
67 |
68 | if (event.getAction() == MotionEvent.ACTION_UP && mListener != null) {
69 | // stop drag and drop mode
70 | mListener.onActionUp(event);
71 | }
72 | // connect GestureDetector with our touch events
73 | return mGestureDetectorCompat.onTouchEvent(event);
74 | }
75 |
76 |
77 | interface ScrollHelperListener {
78 |
79 | boolean onDown(MotionEvent e);
80 |
81 | boolean onSingleTapUp(MotionEvent e);
82 |
83 | void onLongPress(MotionEvent e);
84 |
85 | boolean onActionUp(MotionEvent e);
86 |
87 | boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
88 |
89 | boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ScrollType.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | import static com.cleveroad.adaptivetablelayout.ScrollType.SCROLL_HORIZONTAL;
9 | import static com.cleveroad.adaptivetablelayout.ScrollType.SCROLL_VERTICAL;
10 |
11 | @IntDef({
12 | SCROLL_HORIZONTAL,
13 | SCROLL_VERTICAL
14 | })
15 | /**
16 | * Scroll type for drag and drop mode.
17 | */
18 | @Retention(RetentionPolicy.SOURCE)
19 | @interface ScrollType {
20 | int SCROLL_HORIZONTAL = 0;
21 | int SCROLL_VERTICAL = 1;
22 | }
23 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ShadowHelper.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | class ShadowHelper {
9 |
10 | @Nullable
11 | private View mRightShadow;
12 | @Nullable
13 | private View mLeftShadow;
14 | @Nullable
15 | private View mTopShadow;
16 | @Nullable
17 | private View mBottomShadow;
18 | @Nullable
19 | private View mColumnsHeadersShadow;
20 | @Nullable
21 | private View mRowsHeadersShadow;
22 |
23 | private LayoutDirectionHelper mLayoutDirectionHelper;
24 |
25 | ShadowHelper(LayoutDirectionHelper layoutDirectionHelper) {
26 | mLayoutDirectionHelper = layoutDirectionHelper;
27 | }
28 |
29 | @NonNull
30 | View addColumnsHeadersShadow(ViewGroup group) {
31 | if (mColumnsHeadersShadow == null) {
32 | mColumnsHeadersShadow = new View(group.getContext());
33 | mColumnsHeadersShadow.setBackgroundResource(R.drawable.shadow_bottom);
34 | group.addView(mColumnsHeadersShadow, 0);
35 | }
36 | return mColumnsHeadersShadow;
37 | }
38 |
39 | @Nullable
40 | View getColumnsHeadersShadow() {
41 | return mColumnsHeadersShadow;
42 | }
43 |
44 | @NonNull
45 | View addRowsHeadersShadow(ViewGroup group) {
46 | if (mRowsHeadersShadow == null) {
47 | mRowsHeadersShadow = new View(group.getContext());
48 | mRowsHeadersShadow.setBackgroundResource(!mLayoutDirectionHelper.isRTL()
49 | ? R.drawable.shadow_right
50 | : R.drawable.shadow_left);
51 | group.addView(mRowsHeadersShadow, 0);
52 | }
53 | return mRowsHeadersShadow;
54 | }
55 |
56 | @Nullable
57 | View getRowsHeadersShadow() {
58 | return mRowsHeadersShadow;
59 | }
60 |
61 | void removeColumnsHeadersShadow(ViewGroup group) {
62 | if (mColumnsHeadersShadow != null) {
63 | group.removeView(mColumnsHeadersShadow);
64 | mColumnsHeadersShadow = null;
65 | }
66 | }
67 |
68 | void removeRowsHeadersShadow(ViewGroup group) {
69 | if (mRowsHeadersShadow != null) {
70 | group.removeView(mRowsHeadersShadow);
71 | mRowsHeadersShadow = null;
72 | }
73 | }
74 |
75 | @NonNull
76 | View addLeftShadow(ViewGroup group) {
77 | if (mLeftShadow == null) {
78 | mLeftShadow = new View(group.getContext());
79 | mLeftShadow.setBackgroundResource(R.drawable.shadow_left);
80 | group.addView(mLeftShadow, 0);
81 | }
82 | return mLeftShadow;
83 | }
84 |
85 | @Nullable
86 | View getLeftShadow() {
87 | return mLeftShadow;
88 | }
89 |
90 | @NonNull
91 | View addRightShadow(ViewGroup group) {
92 | if (mRightShadow == null) {
93 | mRightShadow = new View(group.getContext());
94 | mRightShadow.setBackgroundResource(R.drawable.shadow_right);
95 | group.addView(mRightShadow, 0);
96 | }
97 | return mRightShadow;
98 | }
99 |
100 | @Nullable
101 | View getRightShadow() {
102 | return mRightShadow;
103 | }
104 |
105 | @NonNull
106 | View addTopShadow(ViewGroup group) {
107 | if (mTopShadow == null) {
108 | mTopShadow = new View(group.getContext());
109 | mTopShadow.setBackgroundResource(R.drawable.shadow_top);
110 | group.addView(mTopShadow, 0);
111 | }
112 | return mTopShadow;
113 | }
114 |
115 | @Nullable
116 | View getTopShadow() {
117 | return mTopShadow;
118 | }
119 |
120 | @NonNull
121 | View addBottomShadow(ViewGroup group) {
122 | if (mBottomShadow == null) {
123 | mBottomShadow = new View(group.getContext());
124 | mBottomShadow.setBackgroundResource(R.drawable.shadow_bottom);
125 | group.addView(mBottomShadow, 0);
126 | }
127 | return mBottomShadow;
128 | }
129 |
130 | @Nullable
131 | View getBottomShadow() {
132 | return mBottomShadow;
133 | }
134 |
135 | void removeAllDragAndDropShadows(ViewGroup group) {
136 | if (mLeftShadow != null) {
137 | group.removeView(mLeftShadow);
138 | mLeftShadow = null;
139 | }
140 |
141 | if (mRightShadow != null) {
142 | group.removeView(mRightShadow);
143 | mRightShadow = null;
144 | }
145 |
146 | if (mTopShadow != null) {
147 | group.removeView(mTopShadow);
148 | mTopShadow = null;
149 | }
150 |
151 | if (mBottomShadow != null) {
152 | group.removeView(mBottomShadow);
153 | mBottomShadow = null;
154 | }
155 | }
156 |
157 | void onLayoutDirectionChanged() {
158 | if (getRowsHeadersShadow() != null) {
159 | getRowsHeadersShadow().setBackgroundResource(
160 | !mLayoutDirectionHelper.isRTL()
161 | ? R.drawable.shadow_right
162 | : R.drawable.shadow_left);
163 | getRowsHeadersShadow().requestLayout();
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/SmoothScrollRunnable.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.view.View;
4 | import android.widget.Scroller;
5 |
6 | /**
7 | * Fling table layout logic
8 | * {@see http://stackoverflow.com/a/6219382/842697 }
9 | */
10 | class SmoothScrollRunnable implements Runnable {
11 | /**
12 | * Scrollable view
13 | */
14 | private final View mView;
15 | /**
16 | * Need to calculate offset.
17 | */
18 | private Scroller mScroller;
19 |
20 | private int mLastX;
21 | private int mLastY;
22 |
23 | SmoothScrollRunnable(View view) {
24 | mView = view;
25 | mScroller = new Scroller(view.getContext());
26 | }
27 |
28 | void start(int initX, int initY, int initialVelocityX, int initialVelocityY, int maxX, int maxY) {
29 | // start smooth scrolling
30 | mScroller.fling(initX, initY, initialVelocityX, initialVelocityY, 0, maxX, 0, maxY);
31 |
32 | // save new data
33 | mLastX = initX;
34 | mLastY = initY;
35 |
36 | // run self
37 | mView.post(this);
38 | }
39 |
40 | @Override
41 | public void run() {
42 | if (mScroller.isFinished()) {
43 | return;
44 | }
45 | // calculate offset
46 | boolean more = mScroller.computeScrollOffset();
47 | int x = mScroller.getCurrX();
48 | int y = mScroller.getCurrY();
49 | int diffX = mLastX - x;
50 | int diffY = mLastY - y;
51 | if (diffX != 0 || diffY != 0) {
52 | mView.scrollBy(diffX, diffY);
53 | mLastX = x;
54 | mLastY = y;
55 | }
56 |
57 | if (more) {
58 | // run self
59 | mView.post(this);
60 | }
61 | }
62 |
63 | boolean isFinished() {
64 | return mScroller.isFinished();
65 | }
66 |
67 | void forceFinished() {
68 | if (!mScroller.isFinished()) {
69 | mScroller.forceFinished(true);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/SparseMatrix.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.util.SparseArrayCompat;
6 |
7 | import java.util.Collection;
8 | import java.util.LinkedList;
9 |
10 | /**
11 | * Custom matrix realisation to hold Objects
12 | *
13 | * @param Object
14 | */
15 | class SparseMatrix {
16 | private final SparseArrayCompat> mData;
17 |
18 | SparseMatrix() {
19 | mData = new SparseArrayCompat<>();
20 | }
21 |
22 | /**
23 | * Put item to the matrix in row, column position.
24 | *
25 | * @param row item row position
26 | * @param column item column position
27 | * @param item Object
28 | */
29 | void put(int row, int column, @NonNull TObj item) {
30 | SparseArrayCompat array = mData.get(row);
31 | if (array == null) {
32 | array = new SparseArrayCompat<>();
33 | array.put(column, item);
34 | mData.put(row, array);
35 | } else {
36 | array.put(column, item);
37 | }
38 | }
39 |
40 | /**
41 | * Get Object from matrix by row and column.
42 | *
43 | * @param row item row position
44 | * @param column item column position
45 | * @return Object in row, column position in the matrix
46 | */
47 | @Nullable
48 | TObj get(int row, int column) {
49 | SparseArrayCompat array = mData.get(row);
50 | return array == null ? null : array.get(column);
51 | }
52 |
53 | /**
54 | * Get all row's items
55 | *
56 | * @param row row index
57 | * @return Collection with row's Objects
58 | */
59 | @NonNull
60 | Collection getRowItems(int row) {
61 | Collection result = new LinkedList<>();
62 | SparseArrayCompat array = mData.get(row);
63 | for (int count = array.size(), i = 0; i < count; i++) {
64 | int key = array.keyAt(i);
65 | TObj columnObj = array.get(key);
66 | if (columnObj != null) {
67 | result.add(columnObj);
68 | }
69 |
70 | }
71 | return result;
72 | }
73 |
74 | /**
75 | * Get all column's items
76 | *
77 | * @param column column index
78 | * @return Collection with column's Objects
79 | */
80 | @NonNull
81 | Collection getColumnItems(int column) {
82 | Collection result = new LinkedList<>();
83 | for (int count = mData.size(), i = 0; i < count; i++) {
84 | int key = mData.keyAt(i);
85 | TObj columnObj = mData.get(key).get(column);
86 | if (columnObj != null) {
87 | result.add(columnObj);
88 | }
89 |
90 | }
91 | return result;
92 | }
93 |
94 | /**
95 | * Get all matrix's items
96 | *
97 | * @return Collection with column's Objects
98 | */
99 | @NonNull
100 | Collection getAll() {
101 | Collection result = new LinkedList<>();
102 | for (int countR = mData.size(), i = 0; i < countR; i++) {
103 | int rowKey = mData.keyAt(i);
104 | SparseArrayCompat columns = mData.get(rowKey);
105 | for (int countC = columns.size(), j = 0; j < countC; j++) {
106 | int key = columns.keyAt(j);
107 | result.add(columns.get(key));
108 | }
109 | }
110 | return result;
111 | }
112 |
113 | /**
114 | * Remove item in row, column position int the matrix
115 | *
116 | * @param row item row position
117 | * @param column item column position
118 | */
119 | void remove(int row, int column) {
120 | SparseArrayCompat array = mData.get(row);
121 | if (array != null) {
122 | array.remove(column);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.view.View;
5 |
6 | /**
7 | * A {@link ViewHolder} describes an item view and metadata about its place within the {@link AdaptiveTableLayout}.
8 | */
9 | interface ViewHolder {
10 | /**
11 | * @return item represents the item of the {@link AdaptiveTableLayout}
12 | */
13 | @NonNull
14 | View getItemView();
15 |
16 | /**
17 | * @return the type of the View
18 | */
19 | int getItemType();
20 |
21 | /**
22 | * @param itemType is the type of the View
23 | */
24 | void setItemType(int itemType);
25 |
26 | /**
27 | * @return the row index.
28 | */
29 | int getRowIndex();
30 |
31 | /**
32 | * @param rowIndex the row index.
33 | */
34 | void setRowIndex(int rowIndex);
35 |
36 | /**
37 | * @return the column index.
38 | */
39 | int getColumnIndex();
40 |
41 | /**
42 | * @param columnIndex the column index.
43 | */
44 | void setColumnIndex(int columnIndex);
45 |
46 |
47 | /**
48 | * @return dragging flag
49 | */
50 | boolean isDragging();
51 |
52 | /**
53 | * @param isDragging dragging param
54 | */
55 | void setIsDragging(boolean isDragging);
56 | }
57 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ViewHolderImpl.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.view.View;
5 |
6 | /**
7 | * {@inheritDoc}
8 | */
9 | public abstract class ViewHolderImpl implements ViewHolder {
10 | /**
11 | * Holder view
12 | */
13 | private final View mItemView;
14 | /**
15 | * ViewHolder's table row index
16 | */
17 | private int mRowIndex;
18 | /**
19 | * ViewHolder's table column index
20 | */
21 | private int mColIndex;
22 | /**
23 | * ViewHolder's table item type param
24 | */
25 | private int mItemType;
26 | /**
27 | * ViewHolder's dragging flag
28 | */
29 | private boolean mIsDragging;
30 |
31 | public ViewHolderImpl(@NonNull View itemView) {
32 | mItemView = itemView;
33 | }
34 |
35 | @NonNull
36 | @Override
37 | public View getItemView() {
38 | return mItemView;
39 | }
40 |
41 | @Override
42 | public int getRowIndex() {
43 | return mRowIndex;
44 | }
45 |
46 | @Override
47 | public void setRowIndex(int rowIndex) {
48 | mRowIndex = rowIndex;
49 | }
50 |
51 | @Override
52 | public int getColumnIndex() {
53 | return mColIndex;
54 | }
55 |
56 | @Override
57 | public void setColumnIndex(int columnIndex) {
58 | mColIndex = columnIndex;
59 | }
60 |
61 | @Override
62 | public int getItemType() {
63 | return mItemType;
64 | }
65 |
66 | @Override
67 | public void setItemType(int itemType) {
68 | mItemType = itemType;
69 | }
70 |
71 | @Override
72 | public int hashCode() {
73 | int result = mItemView.hashCode();
74 | result = 31 * result + mRowIndex;
75 | result = 31 * result + mColIndex;
76 | result = 31 * result + mItemType;
77 | result = 31 * result + (mIsDragging ? 1 : 0);
78 | return result;
79 | }
80 |
81 | @Override
82 | public boolean equals(Object obj) {
83 | if (!(obj instanceof ViewHolder)) {
84 | return false;
85 | }
86 | ViewHolder vh = (ViewHolder) obj;
87 | return vh.getColumnIndex() == this.getColumnIndex() && vh.getRowIndex() == this.getRowIndex();
88 | }
89 |
90 | @Override
91 | public boolean isDragging() {
92 | return mIsDragging;
93 | }
94 |
95 | @Override
96 | public void setIsDragging(boolean isDragging) {
97 | mIsDragging = isDragging;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/library/src/main/java/com/cleveroad/adaptivetablelayout/ViewHolderType.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.adaptivetablelayout;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | @IntDef({
9 | ViewHolderType.FIRST_HEADER,
10 | ViewHolderType.ROW_HEADER,
11 | ViewHolderType.COLUMN_HEADER,
12 | ViewHolderType.ITEM
13 | })
14 | /**
15 | * Type of adapter's ViewHolders
16 | */
17 | @Retention(RetentionPolicy.SOURCE)
18 | @interface ViewHolderType {
19 | /**
20 | * Top left header
21 | */
22 | int FIRST_HEADER = 0;
23 | /**
24 | * Vertical header
25 | */
26 | int ROW_HEADER = 1;
27 | /**
28 | * Horizontal header
29 | */
30 | int COLUMN_HEADER = 2;
31 | /**
32 | * Normal scrollable item
33 | */
34 | int ITEM = 3;
35 | }
36 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/shadow_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/shadow_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/shadow_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/shadow_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #40000000
4 | #00000000
5 |
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AdaptiveTableLayout
3 |
4 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Android template
3 | # Built application files
4 | *.apk
5 | *.ap_
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 |
18 | # Gradle files
19 | .gradle/
20 | build/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | # Log Files
29 | *.log
30 |
31 | # Android Studio Navigation editor temp files
32 | .navigation/
33 |
34 | # Android Studio captures folder
35 | captures/
36 |
37 | # Intellij
38 | *.iml
39 | .idea/workspace.xml
40 |
41 | # Keystore files
42 | *.jks
43 |
44 | /src/main/res/values/keys.xml
45 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.cleveroad.tablelayout"
7 | minSdkVersion 16
8 | targetSdkVersion 28
9 | versionCode 8
10 | versionName "1.2.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled true
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(include: ['*.jar'], dir: 'libs')
23 | implementation "com.android.support:appcompat-v7:$support_version"
24 | implementation "com.android.support:cardview-v7:$support_version"
25 | implementation "com.android.support:support-v4:$support_version"
26 | implementation "com.android.support:design:$support_version"
27 | // compile 'com.facebook.android:facebook-android-sdk:4.24.0'
28 |
29 | //Glide
30 | implementation "com.github.bumptech.glide:glide:$glide_version"
31 | annotationProcessor "com.github.bumptech.glide:compiler:$glide_version"
32 |
33 | implementation project(':library')
34 | }
35 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/illichenko_cr/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -keep public class * implements com.bumptech.glide.module.GlideModule
20 | -keep public class * extends com.bumptech.glide.module.AppGlideModule
21 | -keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
22 | **[] $VALUES;
23 | public *;
24 | }
25 |
26 | # for DexGuard only
27 | -keepresourcexmlelements manifest/application/meta-data@value=GlideModule
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/sample/src/main/assets/artists.csv:
--------------------------------------------------------------------------------
1 | №, Photo, Name, Song, Genres
2 | 1, https://upload.wikimedia.org/wikipedia/commons/e/e4/Gabriel_batistuta.jpg,Name1,Song1,Rock;Jazz
3 | 2, https://upload.wikimedia.org/wikipedia/commons/e/e2/Hernan.png,Name2,Song2,Rock;Jazz
4 | 3, https://upload.wikimedia.org/wikipedia/commons/b/bb/Mcu_Alfredo_Di_Stefano.jpg,Name3,Song3,Rock;Jazz
5 | 4, https://upload.wikimedia.org/wikipedia/commons/d/db/Mario_Kempes_2006.jpg,Name4,Song4,Rock;Jazz
6 | 5, https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Maradona_at_2012_GCC_Champions_League_final.JPG/228px-Maradona_at_2012_GCC_Champions_League_final.JPG,Name5,Song5,Rock;Jazz
7 | 6, https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Passarella_world_cup.jpg/362px-Passarella_world_cup.jpg,Name6,Song6,Rock;Jazz
8 | 7, https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Saviola_after_Goal.jpg/202px-Saviola_after_Goal.jpg,Name7,Song7,Rock;Jazz
9 | 8, https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/EnriqueSivori_1956.jpeg/174px-EnriqueSivori_1956.jpeg,Name8,Song8,Rock;Jazz
10 | 9, https://upload.wikimedia.org/wikipedia/commons/2/20/JSV-Presidente-Estudiantes-2014.JPG,Name9,Song9,Rock;Jazz
11 | 10, https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Metalist-Inter_%282%29.jpg/159px-Metalist-Inter_%282%29.jpg,Name10,Song10,Rock;Jazz
12 | 11, https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Jan_Ceulemans.jpg/159px-Jan_Ceulemans.jpg,Name11,Song11,Rock;Jazz
13 | 12, https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Jean-Marie_Pfaff_at_Runa_Ralley_2007_cropped.jpg/163px-Jean-Marie_Pfaff_at_Runa_Ralley_2007_cropped.jpg,Name12,Song12,Rock;Jazz
14 | 13, https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Franky_Van_der_Elst_Lommel_United.JPG/161px-Franky_Van_der_Elst_Lommel_United.JPG,Name13,Song13,Rock;Jazz
15 | 14, https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Pele200802FabioRodriguesPozzebomAgenciaBrasil.jpg/155px-Pele200802FabioRodriguesPozzebomAgenciaBrasil.jpg,Name14,Song14,Rock;Jazz
16 | 15, https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Roberto_Carlos_in_Moscow_3.jpg/171px-Roberto_Carlos_in_Moscow_3.jpg,Name15,Song15,Rock;Jazz
17 | 16, https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Ronaldinho_72.jpg/159px-Ronaldinho_72.jpg,Name16,Song16,Rock;Jazz
18 | 17, https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Ronaldo-14-05-2013.jpg/180px-Ronaldo-14-05-2013.jpg,Name17,Song17,Rock;Jazz
19 | 18, https://upload.wikimedia.org/wikipedia/commons/b/b9/Dasaev_Rinat.JPG,Name18,Song18,Rock;Jazz
20 | 19, https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Andriy_Shevchenko_Nike_Clash_Collection.JPG/159px-Andriy_Shevchenko_Nike_Clash_Collection.JPG,Name19,Song19,Rock;Jazz
21 | 20, https://upload.wikimedia.org/wikipedia/commons/d/d2/Mia_Hamm_signing_an_autograph.jpg,Name20,Song20,Rock;Jazz
--------------------------------------------------------------------------------
/sample/src/main/assets/fifa100.csv:
--------------------------------------------------------------------------------
1 | №, Photo, Name, Position, Date of birth, Football team
2 | 1, https://upload.wikimedia.org/wikipedia/commons/e/e4/Gabriel_batistuta.jpg, Gabriel Batistuta, FW, 1969-02-01, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
3 | 2, https://upload.wikimedia.org/wikipedia/commons/e/e2/Hernan.png, Hernán Crespo, FW, 1975-07-05, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
4 | 3, https://upload.wikimedia.org/wikipedia/commons/b/bb/Mcu_Alfredo_Di_Stefano.jpg, Alfredo Di Stéfano, FW, 1926-07-04, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
5 | 4, https://upload.wikimedia.org/wikipedia/commons/d/db/Mario_Kempes_2006.jpg, Mario Kempes, FW, 1954-07-15, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
6 | 5, https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Maradona_at_2012_GCC_Champions_League_final.JPG/228px-Maradona_at_2012_GCC_Champions_League_final.JPG, Diego Maradona, FW/MF, 1960-10-30, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
7 | 6, https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Passarella_world_cup.jpg/362px-Passarella_world_cup.jpg, Daniel Passarella, DF, 1953-05-25, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
8 | 7, https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Saviola_after_Goal.jpg/202px-Saviola_after_Goal.jpg, Javier Saviola, FW, 1981-12-11, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
9 | 8, https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/EnriqueSivori_1956.jpeg/174px-EnriqueSivori_1956.jpeg, Omar Sivori, FW, 1935-10-02, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
10 | 9, https://upload.wikimedia.org/wikipedia/commons/2/20/JSV-Presidente-Estudiantes-2014.JPG, Juan Sebastián Verón, MF, 1975-03-09,https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
11 | 10, https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Metalist-Inter_%282%29.jpg/159px-Metalist-Inter_%282%29.jpg, Javier Zanetti, DF/MF, 1973-08-10, https://upload.wikimedia.org/wikipedia/en/8/84/Afa_logo_jerseys.png
12 | 11, https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Jan_Ceulemans.jpg/159px-Jan_Ceulemans.jpg, Jan Ceulemans, MF, 1957-02-28, https://upload.wikimedia.org/wikipedia/en/f/f5/Belgium_urbsfa.png
13 | 12, https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Jean-Marie_Pfaff_at_Runa_Ralley_2007_cropped.jpg/163px-Jean-Marie_Pfaff_at_Runa_Ralley_2007_cropped.jpg, Jean-Marie Pfaff, GK, 1953-12-04, https://upload.wikimedia.org/wikipedia/en/f/f5/Belgium_urbsfa.png
14 | 13, https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Franky_Van_der_Elst_Lommel_United.JPG/161px-Franky_Van_der_Elst_Lommel_United.JPG, Franky Van der Elst, MF, 1961-04-30, https://upload.wikimedia.org/wikipedia/en/f/f5/Belgium_urbsfa.png
15 | 14, https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Pele200802FabioRodriguesPozzebomAgenciaBrasil.jpg/155px-Pele200802FabioRodriguesPozzebomAgenciaBrasil.jpg, Pelé, FW, 1940-10-23, https://upload.wikimedia.org/wikipedia/en/thumb/9/99/Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg/179px-Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg.png
16 | 15, https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Roberto_Carlos_in_Moscow_3.jpg/171px-Roberto_Carlos_in_Moscow_3.jpg, Roberto Carlos, DF, 1973-04-10, https://upload.wikimedia.org/wikipedia/en/thumb/9/99/Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg/143px-Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg.png
17 | 16, https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Ronaldinho_72.jpg/159px-Ronaldinho_72.jpg, Ronaldinho, MF/FW, 1980-03-21, https://upload.wikimedia.org/wikipedia/en/thumb/9/99/Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg/143px-Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg.png
18 | 17, https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Ronaldo-14-05-2013.jpg/180px-Ronaldo-14-05-2013.jpg, Ronaldo, FW, 1976-09-18,https://upload.wikimedia.org/wikipedia/en/thumb/9/99/Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg/143px-Confedera%C3%A7%C3%A3o_Brasileira_de_Futebol_%28escudo%29.svg.png
19 | 18, https://upload.wikimedia.org/wikipedia/commons/b/b9/Dasaev_Rinat.JPG, Rinat Dasayev, GK, 1957-06-13, https://upload.wikimedia.org/wikipedia/en/7/77/Russian_Football_Union.png
20 | 19, https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Andriy_Shevchenko_Nike_Clash_Collection.JPG/159px-Andriy_Shevchenko_Nike_Clash_Collection.JPG, Andriy Shevchenko, FW, 1976-09-29, https://upload.wikimedia.org/wikipedia/en/thumb/c/c5/Football_Federation_of_Ukraine.svg/106px-Football_Federation_of_Ukraine.svg.png
21 | 20, https://upload.wikimedia.org/wikipedia/commons/d/d2/Mia_Hamm_signing_an_autograph.jpg, Mia Hamm, FW, 1972-03-17, https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/USA_Soccer_Team_logo.svg/174px-USA_Soccer_Team_logo.svg.png
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/SampleApplication.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | public class SampleApplication extends Application {
7 |
8 | private static Context context;
9 |
10 | @Override
11 | public void onCreate() {
12 | super.onCreate();
13 | SampleApplication.context = getApplicationContext();
14 | }
15 |
16 | public static Context getAppContext() {
17 | return SampleApplication.context;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/adapter/SampleLinkedTableAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.adapter;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.drawable.Drawable;
6 | import android.graphics.drawable.GradientDrawable;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.v4.graphics.ColorUtils;
10 | import android.text.TextUtils;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.ImageView;
15 | import android.widget.TextView;
16 |
17 | import com.bumptech.glide.Glide;
18 | import com.bumptech.glide.load.DataSource;
19 | import com.bumptech.glide.load.engine.GlideException;
20 | import com.bumptech.glide.load.resource.bitmap.FitCenter;
21 | import com.bumptech.glide.request.RequestListener;
22 | import com.bumptech.glide.request.RequestOptions;
23 | import com.bumptech.glide.request.target.Target;
24 | import com.cleveroad.adaptivetablelayout.LinkedAdaptiveTableAdapter;
25 | import com.cleveroad.adaptivetablelayout.ViewHolderImpl;
26 | import com.cleveroad.sample.R;
27 | import com.cleveroad.sample.datasource.TableDataSource;
28 |
29 | public class SampleLinkedTableAdapter extends LinkedAdaptiveTableAdapter {
30 | private static final int[] COLORS = new int[]{
31 | 0xffe62a10, 0xffe91e63, 0xff9c27b0, 0xff673ab7, 0xff3f51b5,
32 | 0xff5677fc, 0xff03a9f4, 0xff00bcd4, 0xff009688, 0xff259b24,
33 | 0xff8bc34a, 0xffcddc39, 0xffffeb3b, 0xffffc107, 0xffff9800, 0xffff5722};
34 |
35 | private final LayoutInflater mLayoutInflater;
36 | private final TableDataSource mTableDataSource;
37 | private final int mColumnWidth;
38 | private final int mRowHeight;
39 | private final int mHeaderHeight;
40 | private final int mHeaderWidth;
41 |
42 | public SampleLinkedTableAdapter(Context context, TableDataSource tableDataSource) {
43 | mLayoutInflater = LayoutInflater.from(context);
44 | mTableDataSource = tableDataSource;
45 | Resources res = context.getResources();
46 | mColumnWidth = res.getDimensionPixelSize(R.dimen.column_width);
47 | mRowHeight = res.getDimensionPixelSize(R.dimen.row_height);
48 | mHeaderHeight = res.getDimensionPixelSize(R.dimen.column_header_height);
49 | mHeaderWidth = res.getDimensionPixelSize(R.dimen.row_header_width);
50 | }
51 |
52 | @Override
53 | public int getRowCount() {
54 | return mTableDataSource.getRowsCount();
55 | }
56 |
57 | @Override
58 | public int getColumnCount() {
59 | return mTableDataSource.getColumnsCount();
60 | }
61 |
62 | @NonNull
63 | @Override
64 | public ViewHolderImpl onCreateItemViewHolder(@NonNull ViewGroup parent) {
65 | return new TestViewHolder(mLayoutInflater.inflate(R.layout.item_card, parent, false));
66 | }
67 |
68 | @NonNull
69 | @Override
70 | public ViewHolderImpl onCreateColumnHeaderViewHolder(@NonNull ViewGroup parent) {
71 | return new TestHeaderColumnViewHolder(mLayoutInflater.inflate(R.layout.item_header_column, parent, false));
72 | }
73 |
74 | @NonNull
75 | @Override
76 | public ViewHolderImpl onCreateRowHeaderViewHolder(@NonNull ViewGroup parent) {
77 | return new TestHeaderRowViewHolder(mLayoutInflater.inflate(R.layout.item_header_row, parent, false));
78 | }
79 |
80 | @NonNull
81 | @Override
82 | public ViewHolderImpl onCreateLeftTopHeaderViewHolder(@NonNull ViewGroup parent) {
83 | return new TestHeaderLeftTopViewHolder(mLayoutInflater.inflate(R.layout.item_header_left_top, parent, false));
84 | }
85 |
86 | @Override
87 | public void onBindViewHolder(@NonNull ViewHolderImpl viewHolder, int row, int column) {
88 | final TestViewHolder vh = (TestViewHolder) viewHolder;
89 | String itemData = mTableDataSource.getItemData(row, column); // skip headers
90 |
91 | if (TextUtils.isEmpty(itemData)) {
92 | itemData = "";
93 | }
94 |
95 | itemData = itemData.trim();
96 | vh.tvText.setVisibility(View.VISIBLE);
97 | vh.ivImage.setVisibility(View.VISIBLE);
98 | vh.tvText.setText(itemData);
99 |
100 | Glide.with(vh.ivImage.getContext())
101 | .load(itemData)
102 | .apply(new RequestOptions().transform(new FitCenter()))
103 | .listener(new RequestListener() {
104 | @Override
105 | public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
106 | vh.ivImage.setVisibility(View.INVISIBLE);
107 | vh.tvText.setVisibility(View.VISIBLE);
108 | return false;
109 | }
110 |
111 | @Override
112 | public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
113 | vh.ivImage.setVisibility(View.VISIBLE);
114 | vh.tvText.setVisibility(View.INVISIBLE);
115 | return false;
116 | }
117 | })
118 | .into(vh.ivImage);
119 | }
120 |
121 | @Override
122 | public void onBindHeaderColumnViewHolder(@NonNull ViewHolderImpl viewHolder, int column) {
123 | int color = COLORS[column % COLORS.length];
124 | TestHeaderColumnViewHolder vh = (TestHeaderColumnViewHolder) viewHolder;
125 | vh.tvText.setText(mTableDataSource.getColumnHeaderData(column)); // skip left top header
126 | GradientDrawable gd = new GradientDrawable(
127 | mIsRtl ? GradientDrawable.Orientation.RIGHT_LEFT : GradientDrawable.Orientation.LEFT_RIGHT,
128 | new int[]{ColorUtils.setAlphaComponent(color, 50), 0x00000000});
129 | gd.setCornerRadius(0f);
130 | vh.vGradient.setBackground(gd);
131 | vh.vLine.setBackgroundColor(color);
132 | }
133 |
134 | @Override
135 | public void onBindHeaderRowViewHolder(@NonNull ViewHolderImpl viewHolder, int row) {
136 | TestHeaderRowViewHolder vh = (TestHeaderRowViewHolder) viewHolder;
137 | vh.tvText.setText(mTableDataSource.getItemData(row, 0));
138 | }
139 |
140 | @Override
141 | public void onBindLeftTopHeaderViewHolder(@NonNull ViewHolderImpl viewHolder) {
142 | TestHeaderLeftTopViewHolder vh = (TestHeaderLeftTopViewHolder) viewHolder;
143 | vh.tvText.setText(mTableDataSource.getFirstHeaderData());
144 | }
145 |
146 | @Override
147 | public int getColumnWidth(int column) {
148 | return mColumnWidth;
149 | }
150 |
151 | @Override
152 | public int getHeaderColumnHeight() {
153 | return mHeaderHeight;
154 | }
155 |
156 | @Override
157 | public int getRowHeight(int row) {
158 | return mRowHeight;
159 | }
160 |
161 | @Override
162 | public int getHeaderRowWidth() {
163 | return mHeaderWidth;
164 | }
165 |
166 | //------------------------------------- view holders ------------------------------------------
167 |
168 | private static class TestViewHolder extends ViewHolderImpl {
169 | TextView tvText;
170 | ImageView ivImage;
171 |
172 | private TestViewHolder(@NonNull View itemView) {
173 | super(itemView);
174 | tvText = itemView.findViewById(R.id.tvText);
175 | ivImage = itemView.findViewById(R.id.ivImage);
176 | }
177 | }
178 |
179 | private static class TestHeaderColumnViewHolder extends ViewHolderImpl {
180 | TextView tvText;
181 | View vGradient;
182 | View vLine;
183 |
184 | private TestHeaderColumnViewHolder(@NonNull View itemView) {
185 | super(itemView);
186 | tvText = itemView.findViewById(R.id.tvText);
187 | vGradient = itemView.findViewById(R.id.vGradient);
188 | vLine = itemView.findViewById(R.id.vLine);
189 | }
190 | }
191 |
192 | private static class TestHeaderRowViewHolder extends ViewHolderImpl {
193 | TextView tvText;
194 |
195 | TestHeaderRowViewHolder(@NonNull View itemView) {
196 | super(itemView);
197 | tvText = itemView.findViewById(R.id.tvText);
198 | }
199 | }
200 |
201 | private static class TestHeaderLeftTopViewHolder extends ViewHolderImpl {
202 | TextView tvText;
203 |
204 | private TestHeaderLeftTopViewHolder(@NonNull View itemView) {
205 | super(itemView);
206 | tvText = itemView.findViewById(R.id.tvText);
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/datasource/Constants.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.datasource;
2 |
3 | public class Constants {
4 |
5 | public static final String EXTRA_TITLE = "EXTRA_TITLE";
6 | public static final String EXTRA_VALUE = "EXTRA_VALUE";
7 | public static final String EXTRA_COLUMN_NUMBER = "EXTRA_COLUMN_NUMBER";
8 | public static final String EXTRA_ROW_NUMBER = "EXTRA_ROW_NUMBER";
9 | public static final String EXTRA_BEFORE_OR_AFTER = "EXTRA_BEFORE_OR_AFTER";
10 |
11 | private static int requestCode = 1;
12 | private static int actionChangeData = 1;
13 |
14 | public static final int REQUEST_CODE_EDIT_SONG = generateRequestCode();
15 | public static final int REQUEST_CODE_DELETE_ROW = generateRequestCode();
16 | public static final int REQUEST_CODE_ADD_ROW = generateRequestCode();
17 | public static final int REQUEST_CODE_ADD_ROW_CONFIRMED = generateRequestCode();
18 | public static final int REQUEST_CODE_ADD_COLUMN_CONFIRMED = generateRequestCode();
19 | public static final int REQUEST_CODE_DELETE_COLUMN = generateRequestCode();
20 | public static final int REQUEST_CODE_ADD_COLUMN = generateRequestCode();
21 | public static final int REQUEST_CODE_DELETE_ROW_CONFIRMED = generateRequestCode();
22 | public static final int REQUEST_CODE_DELETE_COLUMN_CONFIRMED = generateRequestCode();
23 | public static final int REQUEST_CODE_SETTINGS = generateRequestCode();
24 |
25 | public static final int ADD_ROW = generateActionChangeData();
26 | public static final int DELETE_ROW = generateActionChangeData();
27 | public static final int ADD_COLUMN = generateActionChangeData();
28 | public static final int DELETE_COLUMN = generateActionChangeData();
29 |
30 | private static int generateActionChangeData(){
31 | return ++actionChangeData;
32 | }
33 |
34 | private static int generateRequestCode(){
35 | return ++requestCode;
36 | }
37 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/datasource/TableDataSource.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.datasource;
2 |
3 | public interface TableDataSource {
4 |
5 | int getRowsCount();
6 |
7 | int getColumnsCount();
8 |
9 | TFirstHeaderDataType getFirstHeaderData();
10 |
11 | TRowHeaderDataType getRowHeaderData(int index);
12 |
13 | TColumnHeaderDataType getColumnHeaderData(int index);
14 |
15 | TItemDataType getItemData(int rowIndex, int columnIndex);
16 | }
17 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/datasource/UpdateFileCallback.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.datasource;
2 |
3 | public interface UpdateFileCallback {
4 |
5 | void onFileUpdated(String fileName, boolean isSuccess);
6 |
7 | void onFileUpdated(String fileName);
8 | }
9 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/provider/DocumentsProvider.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.provider;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.ContentProvider;
5 | import android.content.ContentValues;
6 | import android.content.Context;
7 | import android.database.Cursor;
8 | import android.net.Uri;
9 | import android.os.Environment;
10 | import android.os.StrictMode;
11 | import android.provider.DocumentsContract;
12 | import android.provider.MediaStore;
13 | import android.support.annotation.NonNull;
14 | import android.support.annotation.Nullable;
15 |
16 | import com.cleveroad.sample.SampleApplication;
17 |
18 | import java.io.File;
19 |
20 | public class DocumentsProvider extends ContentProvider {
21 |
22 | @Override
23 | public boolean onCreate() {
24 | return true;
25 | }
26 |
27 | @Nullable
28 | @Override
29 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
30 | return null;
31 | }
32 |
33 | @SuppressLint("NewApi")
34 | @Override
35 | public String getType(@NonNull Uri uri) {
36 | if (DocumentsContract.isDocumentUri(SampleApplication.getAppContext(), uri)) {
37 | if (isExternalStorageDocument(uri)) {// ExternalStorageProvider
38 | final String docId = DocumentsContract.getDocumentId(uri);
39 | final String[] split = docId.split(":");
40 | final String type = split[0];
41 | String storageDefinition;
42 |
43 | if ("primary".equalsIgnoreCase(type)) {
44 | return Environment.getExternalStorageDirectory() + "/" + split[1];
45 | } else {
46 | if (Environment.isExternalStorageRemovable()) {
47 | storageDefinition = "EXTERNAL_STORAGE";
48 | } else {
49 | storageDefinition = "SECONDARY_STORAGE";
50 | }
51 | String path = System.getenv(storageDefinition) + "/" + split[1];
52 |
53 | File file = new File(path);
54 | if (!file.exists()) {
55 | path = "storage/" + type + "/" + split[1];
56 | file = new File(path.trim());
57 | if (!file.exists() || file.isDirectory()) {
58 | throw new NullPointerException("Couldn't find file path -> " + path);
59 | }
60 | }
61 | return path;
62 | }
63 | } else if (isDownloadsDocument(uri)) {
64 | final String id = DocumentsContract.getDocumentId(uri);
65 | if (id.contains("raw:")) {
66 | final String[] idArray = id.split("raw:");
67 | return idArray[1];
68 | } else {
69 | return null;
70 | }
71 |
72 | } else if (isMediaDocument(uri)) {// MediaProvider
73 | final String docId = DocumentsContract.getDocumentId(uri);
74 | final String[] split = docId.split(":");
75 | final String type = split[0];
76 |
77 | Uri contentUri = null;
78 | if ("image".equals(type)) {
79 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
80 | } else if ("video".equals(type)) {
81 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
82 | } else if ("audio".equals(type)) {
83 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
84 | }
85 |
86 | final String selection = "_id=?";
87 | final String[] selectionArgs = new String[]{
88 | split[1]
89 | };
90 | return getDataColumn(SampleApplication.getAppContext(), contentUri, selection, selectionArgs);
91 | }
92 | } else if ("content".equalsIgnoreCase(uri.getScheme())) {// MediaStore (and general)
93 | // Return the remote address
94 | if (isGooglePhotosUri(uri)) {
95 | return uri.getLastPathSegment();
96 | }
97 | return getDataColumn(SampleApplication.getAppContext(), uri, null, null);
98 | } else if ("file".equalsIgnoreCase(uri.getScheme())) {// File
99 | return uri.getPath();
100 | }
101 | return null;
102 | }
103 |
104 | @Nullable
105 | @Override
106 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
107 | return null;
108 | }
109 |
110 | @Override
111 | public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
112 | return 0;
113 | }
114 |
115 | @Override
116 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
117 | return 0;
118 | }
119 |
120 |
121 | public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
122 | Cursor cursor = null;
123 | final String column = "_data";
124 | final String[] projection = {
125 | column
126 | };
127 |
128 | try {
129 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
130 | if (cursor != null && cursor.moveToFirst()) {
131 | StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
132 | StrictMode.setVmPolicy(builder.build());
133 | final int columnIndex = cursor.getColumnIndexOrThrow(column);
134 | return cursor.getString(columnIndex);
135 | }
136 | } finally {
137 | if (cursor != null) {
138 | cursor.close();
139 | }
140 | }
141 | return null;
142 | }
143 |
144 | public static boolean isExternalStorageDocument(Uri uri) {
145 | return "com.android.externalstorage.documents".equals(uri.getAuthority());
146 | }
147 |
148 |
149 | public static boolean isDownloadsDocument(Uri uri) {
150 | return "com.android.providers.downloads.documents".equals(uri.getAuthority());
151 | }
152 |
153 | public static boolean isMediaDocument(Uri uri) {
154 | return "com.android.providers.media.documents".equals(uri.getAuthority());
155 | }
156 |
157 | public static boolean isGooglePhotosUri(Uri uri) {
158 | return "com.google.android.apps.photos.content".equals(uri.getAuthority());
159 | }
160 | }
161 |
162 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/CsvPickerFragment.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.content.pm.PackageManager;
8 | import android.graphics.Color;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.support.annotation.NonNull;
13 | import android.support.annotation.Nullable;
14 | import android.support.v4.app.Fragment;
15 | import android.text.SpannableString;
16 | import android.text.Spanned;
17 | import android.text.TextPaint;
18 | import android.text.TextUtils;
19 | import android.text.method.LinkMovementMethod;
20 | import android.text.style.ClickableSpan;
21 | import android.view.LayoutInflater;
22 | import android.view.View;
23 | import android.view.ViewGroup;
24 | import android.widget.TextView;
25 |
26 | import com.cleveroad.sample.R;
27 | import com.cleveroad.sample.provider.DocumentsProvider;
28 | import com.cleveroad.sample.utils.FileUtils;
29 | import com.cleveroad.sample.utils.PermissionHelper;
30 |
31 | import java.io.File;
32 | import java.io.IOException;
33 | import java.io.InputStream;
34 | import java.util.Objects;
35 |
36 | import static android.content.Intent.EXTRA_MIME_TYPES;
37 |
38 | public class CsvPickerFragment extends Fragment implements View.OnClickListener {
39 | private static final int REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE = 1;
40 | private static final int REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE_DEMO = 3;
41 | private static final int REQUEST_CODE_PICK_CSV = 2;
42 | private static final int START_CHARACTER = 33;
43 | private static final int END_CHARACTER = 37;
44 | private TextView tvPickFile;
45 |
46 | public static CsvPickerFragment newInstance() {
47 | Bundle args = new Bundle();
48 | CsvPickerFragment fragment = new CsvPickerFragment();
49 | fragment.setArguments(args);
50 | return fragment;
51 | }
52 |
53 | @Override
54 | public void onCreate(@Nullable Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 | setRetainInstance(true);
57 | }
58 |
59 | @Nullable
60 | @Override
61 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
62 | View view = inflater.inflate(R.layout.fragment_csv_picker, container, false);
63 | view.findViewById(R.id.bPickFile).setOnClickListener(this);
64 | tvPickFile = view.findViewById(R.id.tvPickFile);
65 | return view;
66 | }
67 |
68 | @Override
69 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
70 | super.onViewCreated(view, savedInstanceState);
71 | SpannableString ss = new SpannableString(getString(R.string.pick_csv_or_demo_file));
72 | ClickableSpan clickableSpan = new ClickableSpan() {
73 | @Override
74 | public void onClick(View textView) {
75 | if (PermissionHelper.checkOrRequest(CsvPickerFragment.this, REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE_DEMO,
76 | Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
77 | createDemoFile();
78 | }
79 | }
80 |
81 | @Override
82 | public void updateDrawState(TextPaint ds) {
83 | super.updateDrawState(ds);
84 | ds.setUnderlineText(false);
85 | }
86 | };
87 | ss.setSpan(clickableSpan, START_CHARACTER, END_CHARACTER, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
88 |
89 | tvPickFile.setText(ss);
90 | tvPickFile.setMovementMethod(LinkMovementMethod.getInstance());
91 | tvPickFile.setHighlightColor(Color.TRANSPARENT);
92 | }
93 |
94 | @Override
95 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
96 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
97 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
98 | switch (requestCode) {
99 | case REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE:
100 | pickCsvFile();
101 | break;
102 | case REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE_DEMO:
103 | createDemoFile();
104 | break;
105 | }
106 | }
107 | }
108 |
109 | @SuppressLint("NewApi")
110 | @Override
111 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
112 | super.onActivityResult(requestCode, resultCode, data);
113 | DocumentsProvider documentsProvider = new DocumentsProvider();
114 | if (requestCode == REQUEST_CODE_PICK_CSV && data != null && resultCode == Activity.RESULT_OK) {
115 | Activity activity = getActivity();
116 | if (activity instanceof OnCsvFileSelectedListener) {
117 | ((OnCsvFileSelectedListener) activity).onCsvFileSelected(documentsProvider.getType(data.getData()));
118 | }
119 | }
120 | }
121 |
122 | @Override
123 | public void onClick(View v) {
124 | if (PermissionHelper.checkOrRequest(this, REQUEST_CODE_PERMISSION_READ_EXTERNAL_STORAGE,
125 | Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
126 | pickCsvFile();
127 | }
128 | }
129 |
130 | private void pickCsvFile() {
131 | String[] mimeTypes = {"text/comma-separated-values", "text/csv"};
132 | Intent intent;
133 |
134 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
135 | intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
136 | intent.putExtra(EXTRA_MIME_TYPES, mimeTypes);
137 | intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
138 | } else {
139 | intent = new Intent(Intent.ACTION_GET_CONTENT);
140 | }
141 |
142 | intent.setType("*/*");
143 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
144 | startActivityForResult(Intent.createChooser(intent, getString(R.string.pick_file)), REQUEST_CODE_PICK_CSV);
145 | }
146 |
147 | private void createDemoFile() {
148 | File file = createDemoTempFile();
149 | try {
150 | if (!file.exists() && file.createNewFile()) {
151 | InputStream inputStream = null;
152 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
153 | inputStream = Objects.requireNonNull(getContext()).getAssets().open("fifa100.csv");
154 | }
155 | FileUtils.copy(inputStream, file);
156 | }
157 | } catch (IOException e) {
158 | e.printStackTrace();
159 | file = null;
160 | }
161 |
162 | String path = file == null ? "" : file.getPath();
163 |
164 | if (!TextUtils.isEmpty(path)) {
165 | Activity activity = getActivity();
166 | if (activity instanceof OnCsvFileSelectedListener) {
167 | ((OnCsvFileSelectedListener) activity).onCsvFileSelected(path);
168 | }
169 | }
170 | }
171 |
172 | public File createDemoTempFile() {
173 | String tempFileName = "DEMO_table_layout_application.csv";
174 | return new File(Environment.getExternalStorageDirectory(), tempFileName);
175 | }
176 |
177 | interface OnCsvFileSelectedListener {
178 | void onCsvFileSelected(String file);
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/SampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.widget.Toast;
6 |
7 | import com.cleveroad.sample.R;
8 |
9 | import java.io.File;
10 |
11 | public class SampleActivity extends AppCompatActivity implements
12 | CsvPickerFragment.OnCsvFileSelectedListener {
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_sample);
17 | if (savedInstanceState == null) {
18 | getSupportFragmentManager()
19 | .beginTransaction()
20 | .add(R.id.container, CsvPickerFragment.newInstance(), CsvPickerFragment.class.getSimpleName())
21 | .commit();
22 | }
23 | }
24 |
25 | @Override
26 | public void onCsvFileSelected(String fileName) {
27 | if (fileName != null && !fileName.isEmpty()) {
28 | File file = new File(fileName);
29 | if (file.exists() && fileName.endsWith(".csv")) {
30 | getSupportFragmentManager()
31 | .beginTransaction()
32 | .replace(R.id.container, TableLayoutFragment.newInstance(fileName), CsvPickerFragment.class.getSimpleName())
33 | .addToBackStack(CsvPickerFragment.class.getSimpleName())
34 | .commit();
35 | } else {
36 | Toast.makeText(this, R.string.not_csv_file_error, Toast.LENGTH_SHORT).show();
37 | }
38 | } else {
39 | Toast.makeText(this, R.string.no_such_file_error, Toast.LENGTH_SHORT).show();
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/dialogs/AddColumnDialog.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui.dialogs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Bundle;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.v4.app.DialogFragment;
10 | import android.support.v4.app.Fragment;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 |
15 | import com.cleveroad.sample.R;
16 |
17 | import static com.cleveroad.sample.datasource.Constants.EXTRA_BEFORE_OR_AFTER;
18 | import static com.cleveroad.sample.datasource.Constants.EXTRA_COLUMN_NUMBER;
19 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_ADD_COLUMN_CONFIRMED;
20 |
21 | public class AddColumnDialog extends DialogFragment implements View.OnClickListener {
22 | private int mColumn;
23 |
24 | public static AddColumnDialog newInstance(int column) {
25 | AddColumnDialog fragment = new AddColumnDialog();
26 | Bundle args = new Bundle();
27 | args.putInt(EXTRA_COLUMN_NUMBER, column);
28 | fragment.setArguments(args);
29 | return fragment;
30 | }
31 |
32 | @Override
33 | public void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | Bundle args = getArguments();
36 | if (args != null) {
37 | mColumn = args.getInt(EXTRA_COLUMN_NUMBER);
38 | }
39 | }
40 |
41 | @Override
42 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
43 | //noinspection ConstantConditions
44 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
45 | return inflater.inflate(R.layout.dialog_add_column, container, false);
46 | }
47 |
48 | @Override
49 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
50 | super.onViewCreated(view, savedInstanceState);
51 | view.findViewById(R.id.bColumnRight).setOnClickListener(this);
52 | view.findViewById(R.id.bColumnLeft).setOnClickListener(this);
53 | view.findViewById(R.id.bNegative).setOnClickListener(this);
54 | }
55 |
56 | @Override
57 | public void onClick(View v) {
58 | switch (v.getId()) {
59 | case R.id.bColumnRight:
60 | sendResult(mColumn, false);
61 | break;
62 | case R.id.bColumnLeft:
63 | sendResult(mColumn, true);
64 | break;
65 | case R.id.bNegative:
66 | // negative
67 | Fragment fragment = getParentFragment();
68 | if (fragment != null) {
69 | fragment.onActivityResult(REQUEST_CODE_ADD_COLUMN_CONFIRMED, Activity.RESULT_CANCELED, null);
70 | }
71 | break;
72 | default:
73 | //do nothing
74 | }
75 | dismiss();
76 | }
77 |
78 | private void sendResult(int column, boolean beforeORAfter) {
79 | Fragment fragment = getParentFragment();
80 | if (fragment != null) {
81 | Intent intent = new Intent();
82 | intent.putExtra(EXTRA_COLUMN_NUMBER, column);
83 | intent.putExtra(EXTRA_BEFORE_OR_AFTER, beforeORAfter);
84 | fragment.onActivityResult(REQUEST_CODE_ADD_COLUMN_CONFIRMED, Activity.RESULT_OK, intent);
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/dialogs/AddRowDialog.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui.dialogs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.DialogFragment;
9 | import android.support.v4.app.Fragment;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.cleveroad.sample.R;
15 |
16 | import static com.cleveroad.sample.datasource.Constants.EXTRA_BEFORE_OR_AFTER;
17 | import static com.cleveroad.sample.datasource.Constants.EXTRA_ROW_NUMBER;
18 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_ADD_ROW_CONFIRMED;
19 |
20 | public class AddRowDialog extends DialogFragment implements View.OnClickListener {
21 |
22 | private int mRow;
23 |
24 | public static AddRowDialog newInstance(int row) {
25 | AddRowDialog fragment = new AddRowDialog();
26 | Bundle args = new Bundle();
27 | args.putInt(EXTRA_ROW_NUMBER, row);
28 | fragment.setArguments(args);
29 | return fragment;
30 | }
31 |
32 | @Override
33 | public void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | Bundle args = getArguments();
36 | if (args != null) {
37 | mRow = args.getInt(EXTRA_ROW_NUMBER);
38 | }
39 | }
40 |
41 | @Override
42 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
43 | //noinspection ConstantConditions
44 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
45 | return inflater.inflate(R.layout.dialog_add_row, container, false);
46 | }
47 |
48 | @Override
49 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
50 | super.onViewCreated(view, savedInstanceState);
51 |
52 | view.findViewById(R.id.bAbove).setOnClickListener(this);
53 | view.findViewById(R.id.bBelow).setOnClickListener(this);
54 | view.findViewById(R.id.bNegative).setOnClickListener(this);
55 | }
56 |
57 | @Override
58 | public void onClick(View v) {
59 | switch (v.getId()) {
60 | case R.id.bAbove:
61 | sendResult(mRow, true);
62 | break;
63 | case R.id.bBelow:
64 | sendResult(mRow, false);
65 | break;
66 | case R.id.bNegative:
67 | // negative
68 | Fragment fragment = getParentFragment();
69 | if (fragment != null) {
70 | fragment.onActivityResult(REQUEST_CODE_ADD_ROW_CONFIRMED, Activity.RESULT_CANCELED, null);
71 | }
72 | break;
73 | default:
74 | //do nothing
75 | }
76 |
77 | dismiss();
78 | }
79 |
80 | private void sendResult(int row, boolean beforeORAfter) {
81 | Fragment fragment = getParentFragment();
82 | if (fragment != null) {
83 | Intent intent = new Intent();
84 | intent.putExtra(EXTRA_ROW_NUMBER, row);
85 | intent.putExtra(EXTRA_BEFORE_OR_AFTER, beforeORAfter);
86 | fragment.onActivityResult(REQUEST_CODE_ADD_ROW_CONFIRMED, Activity.RESULT_OK, intent);
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/dialogs/DeleteDialog.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui.dialogs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.DialogFragment;
9 | import android.support.v4.app.Fragment;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.TextView;
14 |
15 | import com.cleveroad.sample.R;
16 |
17 | import static com.cleveroad.sample.datasource.Constants.EXTRA_COLUMN_NUMBER;
18 | import static com.cleveroad.sample.datasource.Constants.EXTRA_ROW_NUMBER;
19 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_DELETE_COLUMN_CONFIRMED;
20 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_DELETE_ROW_CONFIRMED;
21 |
22 | public class DeleteDialog extends DialogFragment implements View.OnClickListener {
23 | private static final int ZERO_COLUMN_OR_ROW = 0;
24 | private TextView tvTitle;
25 | private int mRow;
26 | private int mColumn;
27 |
28 | public static DeleteDialog newInstance(int row, int column) {
29 | DeleteDialog fragment = new DeleteDialog();
30 | Bundle args = new Bundle();
31 | args.putInt(EXTRA_ROW_NUMBER, row);
32 | args.putInt(EXTRA_COLUMN_NUMBER, column);
33 | fragment.setArguments(args);
34 | return fragment;
35 | }
36 |
37 | @Override
38 | public void onCreate(@Nullable Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | Bundle args = getArguments();
41 | if (args != null) {
42 | mRow = args.getInt(EXTRA_ROW_NUMBER);
43 | mColumn = args.getInt(EXTRA_COLUMN_NUMBER);
44 | }
45 | }
46 |
47 | @Override
48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
49 | //noinspection ConstantConditions
50 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
51 | return inflater.inflate(R.layout.dialog_delete, container, false);
52 | }
53 |
54 | @Override
55 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
56 | super.onViewCreated(view, savedInstanceState);
57 |
58 | view.findViewById(R.id.bPositive).setOnClickListener(this);
59 | view.findViewById(R.id.bNegative).setOnClickListener(this);
60 | tvTitle = (TextView) view.findViewById(R.id.tvTitle);
61 | updateUi();
62 | }
63 |
64 | @Override
65 | public void onClick(View v) {
66 | switch (v.getId()) {
67 | case R.id.bPositive:
68 | // positive
69 | delete();
70 | break;
71 | case R.id.bNegative:
72 | // negative
73 | Fragment fragment = getParentFragment();
74 | if (fragment != null) {
75 | fragment.onActivityResult(REQUEST_CODE_DELETE_ROW_CONFIRMED, Activity.RESULT_CANCELED, null);
76 | }
77 | break;
78 | default:
79 | //do nothing
80 | }
81 |
82 | dismiss();
83 | }
84 |
85 | private void updateUi() {
86 |
87 | if (mColumn == ZERO_COLUMN_OR_ROW) {
88 | tvTitle.setText(getString(R.string.delete_row));
89 | } else if (mRow == ZERO_COLUMN_OR_ROW) {
90 | tvTitle.setText(getString(R.string.delete_column));
91 | }
92 | }
93 |
94 | private void delete(){
95 | if (mColumn == ZERO_COLUMN_OR_ROW) {
96 | sendResult(EXTRA_ROW_NUMBER, mRow, REQUEST_CODE_DELETE_ROW_CONFIRMED);
97 | } else if (mRow == ZERO_COLUMN_OR_ROW) {
98 | sendResult(EXTRA_COLUMN_NUMBER, mColumn, REQUEST_CODE_DELETE_COLUMN_CONFIRMED);
99 | }
100 | }
101 |
102 | private void sendResult(String extra, int data, int requestCode) {
103 | Fragment fragment = getParentFragment();
104 | if (fragment != null) {
105 | Intent intent = new Intent();
106 | intent.putExtra(extra, data);
107 | fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
108 | }
109 | }
110 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/dialogs/EditItemDialog.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui.dialogs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.Nullable;
10 | import android.support.design.widget.TextInputEditText;
11 | import android.support.design.widget.TextInputLayout;
12 | import android.support.v4.app.DialogFragment;
13 | import android.support.v4.app.Fragment;
14 | import android.util.DisplayMetrics;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.view.Window;
19 | import android.widget.TextView;
20 |
21 | import com.cleveroad.sample.R;
22 |
23 | import java.util.Objects;
24 |
25 | import static com.cleveroad.sample.datasource.Constants.EXTRA_COLUMN_NUMBER;
26 | import static com.cleveroad.sample.datasource.Constants.EXTRA_ROW_NUMBER;
27 | import static com.cleveroad.sample.datasource.Constants.EXTRA_TITLE;
28 | import static com.cleveroad.sample.datasource.Constants.EXTRA_VALUE;
29 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_ADD_COLUMN;
30 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_ADD_ROW;
31 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_DELETE_COLUMN;
32 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_DELETE_ROW;
33 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_EDIT_SONG;
34 |
35 | public class EditItemDialog extends DialogFragment implements View.OnClickListener {
36 | private static final int ZERO_COLUMN_OR_ROW = 0;
37 | private String mTitle;
38 | private String mValue;
39 | private int mColumn;
40 | private int mRow;
41 |
42 | private TextInputLayout mTilValue;
43 | private TextInputEditText mEtValue;
44 | private TextView mTvDelete;
45 | private TextView mTvAdd;
46 |
47 | public static EditItemDialog newInstance(int row, int column, String title, String value) {
48 | EditItemDialog dialog = new EditItemDialog();
49 | Bundle args = new Bundle();
50 | args.putInt(EXTRA_COLUMN_NUMBER, column);
51 | args.putInt(EXTRA_ROW_NUMBER, row);
52 | args.putString(EXTRA_TITLE, title);
53 | args.putString(EXTRA_VALUE, value);
54 | dialog.setArguments(args);
55 | return dialog;
56 | }
57 |
58 | @Override
59 | public void onCreate(@Nullable Bundle savedInstanceState) {
60 | super.onCreate(savedInstanceState);
61 | Bundle args = getArguments();
62 | if (args != null) {
63 | mColumn = args.getInt(EXTRA_COLUMN_NUMBER);
64 | mRow = args.getInt(EXTRA_ROW_NUMBER);
65 | mTitle = args.getString(EXTRA_TITLE);
66 | mValue = args.getString(EXTRA_VALUE);
67 | }
68 | }
69 |
70 | @Nullable
71 | @Override
72 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
73 | @Nullable Bundle savedInstanceState) {
74 | //noinspection ConstantConditions
75 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
76 | View view = inflater.inflate(R.layout.dialog_edit_item, container, false);
77 |
78 | mTilValue = view.findViewById(R.id.tilValue);
79 | mEtValue = view.findViewById(R.id.etValue);
80 | mTvDelete = view.findViewById(R.id.tvDelete);
81 | mTvAdd = view.findViewById(R.id.tvAdd);
82 |
83 | mTvDelete.setOnClickListener(this);
84 | mTvAdd.setOnClickListener(this);
85 |
86 | view.findViewById(R.id.bPositive).setOnClickListener(this);
87 | view.findViewById(R.id.bNegative).setOnClickListener(this);
88 |
89 | return view;
90 | }
91 |
92 | @Override
93 | public void onResume() {
94 | super.onResume();
95 | Window window = getDialog().getWindow();
96 | if (window != null) {
97 | DisplayMetrics dm = new DisplayMetrics();
98 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
99 | Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getMetrics(dm);
100 | }
101 | int height = dm.heightPixels;
102 | int width = dm.widthPixels;
103 | window.setLayout(width, height);
104 | window.setLayout((int) (width * 0.8), (int) (height * 0.9));
105 | }
106 | }
107 |
108 | @Override
109 | public void onStart() {
110 | super.onStart();
111 | updateUiAccordingToModel();
112 | }
113 |
114 | @Override
115 | public void onClick(View v) {
116 | switch (v.getId()) {
117 | case R.id.bPositive:
118 | sendResult();
119 | break;
120 | case R.id.bNegative:
121 | Fragment fragment = getParentFragment();
122 | if (fragment != null) {
123 | fragment.onActivityResult(REQUEST_CODE_EDIT_SONG, Activity.RESULT_CANCELED, null);
124 | }
125 | break;
126 | case R.id.tvDelete:
127 | delete();
128 | break;
129 | case R.id.tvAdd:
130 | add();
131 | break;
132 | default:
133 | //do nothing
134 | }
135 |
136 | dismiss();
137 | }
138 |
139 | private void updateUiAccordingToModel() {
140 | mTilValue.setHint(mTitle);
141 | mEtValue.setText(mValue);
142 |
143 | if (mColumn == ZERO_COLUMN_OR_ROW) {
144 | mTvDelete.setText(getString(R.string.delete_row));
145 | mTvAdd.setText(getString(R.string.add_row));
146 | } else if (mRow == ZERO_COLUMN_OR_ROW) {
147 | mTvDelete.setText(getString(R.string.delete_column));
148 | mTvAdd.setText(getString(R.string.add_column));
149 | } else {
150 | mTvDelete.setVisibility(View.GONE);
151 | mTvAdd.setVisibility(View.GONE);
152 | }
153 | }
154 |
155 | private void delete() {
156 | if (mColumn == ZERO_COLUMN_OR_ROW) {
157 | sendResult(EXTRA_ROW_NUMBER, mRow, REQUEST_CODE_DELETE_ROW);
158 | } else if (mRow == ZERO_COLUMN_OR_ROW) {
159 | sendResult(EXTRA_COLUMN_NUMBER, mColumn, REQUEST_CODE_DELETE_COLUMN);
160 | }
161 | }
162 |
163 | private void add() {
164 | if (mColumn == ZERO_COLUMN_OR_ROW) {
165 | sendResult(EXTRA_ROW_NUMBER, mRow, REQUEST_CODE_ADD_ROW);
166 | } else if (mRow == ZERO_COLUMN_OR_ROW) {
167 | sendResult(EXTRA_COLUMN_NUMBER, mColumn, REQUEST_CODE_ADD_COLUMN);
168 | }
169 | }
170 |
171 | private void sendResult() {
172 | Fragment fragment = getParentFragment();
173 | if (fragment != null) {
174 | Intent intent = new Intent();
175 | String str = mEtValue.getText().toString().trim();
176 | intent.putExtra(EXTRA_VALUE, str.isEmpty() ? " " : str);
177 | intent.putExtra(EXTRA_COLUMN_NUMBER, mColumn);
178 | intent.putExtra(EXTRA_ROW_NUMBER, mRow);
179 | fragment.onActivityResult(REQUEST_CODE_EDIT_SONG, Activity.RESULT_OK, intent);
180 | }
181 | }
182 |
183 | private void sendResult(String extra, int data, int requestCode) {
184 | Fragment fragment = getParentFragment();
185 | if (fragment != null) {
186 | Intent intent = new Intent();
187 | intent.putExtra(extra, data);
188 | fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent);
189 | }
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/ui/dialogs/SettingsDialog.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.ui.dialogs;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.Nullable;
10 | import android.support.v4.app.DialogFragment;
11 | import android.support.v4.app.Fragment;
12 | import android.support.v7.widget.SwitchCompat;
13 | import android.util.DisplayMetrics;
14 | import android.view.LayoutInflater;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.view.Window;
18 | import android.widget.CompoundButton;
19 |
20 | import com.cleveroad.sample.R;
21 |
22 | import java.util.Objects;
23 |
24 | import static com.cleveroad.sample.datasource.Constants.REQUEST_CODE_SETTINGS;
25 |
26 | public class SettingsDialog extends DialogFragment implements View.OnClickListener {
27 |
28 | public static final String EXTRA_VALUE_SOLID_HEADER = "EXTRA_VALUE_SOLID_HEADER";
29 | public static final String EXTRA_VALUE_HEADER_FIXED = "EXTRA_VALUE_HEADER_FIXED";
30 | public static final String EXTRA_VALUE_RTL_DIRECTION = "EXTRA_VALUE_RTL_DIRECTION";
31 | public static final String EXTRA_VALUE_DRAG_AND_DROP_ENABLED = "EXTRA_VALUE_DRAG_AND_DROP_ENABLED";
32 |
33 | /**
34 | * if true - value of row header fixed to the row. Fixed to the data
35 | * if false - fixed to the number of row. Fixed to the row' number from 0 to n.
36 | */
37 | private boolean mSolidRowHeader;
38 |
39 | private boolean mIsHeaderFixed;
40 |
41 | private boolean mIsRtlDirection;
42 |
43 | private boolean mIsDragAndDropEnabled;
44 |
45 | private SwitchCompat swSolidRow;
46 |
47 | private SwitchCompat swFixedHeaders;
48 |
49 | private SwitchCompat swRtlDirection;
50 |
51 | private SwitchCompat swDragAndDropEnabled;
52 |
53 |
54 | public static SettingsDialog newInstance(boolean isHeaderFixed, boolean solidRowHeader,
55 | boolean isRtlDirection, boolean isDragAndDropEnabled) {
56 | SettingsDialog dialog = new SettingsDialog();
57 | Bundle args = new Bundle();
58 | args.putBoolean(EXTRA_VALUE_HEADER_FIXED, isHeaderFixed);
59 | args.putBoolean(EXTRA_VALUE_SOLID_HEADER, solidRowHeader);
60 | args.putBoolean(EXTRA_VALUE_RTL_DIRECTION, isRtlDirection);
61 | args.putBoolean(EXTRA_VALUE_DRAG_AND_DROP_ENABLED, isDragAndDropEnabled);
62 | dialog.setArguments(args);
63 | return dialog;
64 | }
65 |
66 | public static SettingsDialog newInstance(boolean isHeaderFixed, boolean solidRowHeader, boolean isDragAndDropEnabled) {
67 | SettingsDialog dialog = new SettingsDialog();
68 | Bundle args = new Bundle();
69 | args.putBoolean(EXTRA_VALUE_HEADER_FIXED, isHeaderFixed);
70 | args.putBoolean(EXTRA_VALUE_SOLID_HEADER, solidRowHeader);
71 | args.putBoolean(EXTRA_VALUE_DRAG_AND_DROP_ENABLED, isDragAndDropEnabled);
72 | dialog.setArguments(args);
73 | return dialog;
74 | }
75 |
76 | @Override
77 | public void onCreate(@Nullable Bundle savedInstanceState) {
78 | super.onCreate(savedInstanceState);
79 | Bundle args = getArguments();
80 | if (args != null) {
81 | mSolidRowHeader = args.getBoolean(EXTRA_VALUE_SOLID_HEADER);
82 | mIsHeaderFixed = args.getBoolean(EXTRA_VALUE_HEADER_FIXED);
83 | mIsRtlDirection = args.getBoolean(EXTRA_VALUE_RTL_DIRECTION);
84 | mIsDragAndDropEnabled = args.getBoolean(EXTRA_VALUE_DRAG_AND_DROP_ENABLED);
85 | }
86 | }
87 |
88 | @Nullable
89 | @Override
90 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
91 | @Nullable Bundle savedInstanceState) {
92 | //noinspection ConstantConditions
93 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
94 | View view = inflater.inflate(R.layout.dialog_settings, container, false);
95 | swSolidRow = view.findViewById(R.id.swSolidRow);
96 | swFixedHeaders = view.findViewById(R.id.swFixedHeaders);
97 | swRtlDirection = view.findViewById(R.id.swRtlDirection);
98 | swDragAndDropEnabled = view.findViewById(R.id.swDragAndDropEnabled);
99 |
100 | return view;
101 | }
102 |
103 | @Override
104 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
105 | super.onViewCreated(view, savedInstanceState);
106 |
107 | view.findViewById(R.id.bPositive).setOnClickListener(this);
108 | view.findViewById(R.id.bNegative).setOnClickListener(this);
109 |
110 | swFixedHeaders.setChecked(mIsHeaderFixed);
111 | swSolidRow.setChecked(mSolidRowHeader);
112 | swRtlDirection.setChecked(mIsRtlDirection);
113 | swDragAndDropEnabled.setChecked(mIsDragAndDropEnabled);
114 |
115 | swFixedHeaders.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
116 | @Override
117 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
118 | mIsHeaderFixed = isChecked;
119 | }
120 | });
121 | swSolidRow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
122 | @Override
123 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
124 | mSolidRowHeader = isChecked;
125 | }
126 | });
127 | swRtlDirection.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
128 | @Override
129 | public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
130 | mIsRtlDirection = isChecked;
131 | }
132 | });
133 | swDragAndDropEnabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
134 | @Override
135 | public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
136 | mIsDragAndDropEnabled = isChecked;
137 | }
138 | });
139 |
140 | }
141 |
142 | @Override
143 | public void onResume() {
144 | super.onResume();
145 | Window window = getDialog().getWindow();
146 | if (window != null) {
147 | DisplayMetrics dm = new DisplayMetrics();
148 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
149 | Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay().getMetrics(dm);
150 | }
151 | int height = dm.heightPixels;
152 | int width = dm.widthPixels;
153 | window.setLayout(width, height);
154 | window.setLayout((int) (width * 0.8), (int) (height * 0.9));
155 | }
156 | }
157 |
158 | @Override
159 | public void onClick(View v) {
160 | switch (v.getId()) {
161 | case R.id.bPositive:
162 | sendResult();
163 | break;
164 | case R.id.bNegative:
165 | Fragment fragment = getParentFragment();
166 | if (fragment != null) {
167 | fragment.onActivityResult(REQUEST_CODE_SETTINGS, Activity.RESULT_CANCELED, null);
168 | }
169 | break;
170 | default:
171 | //do nothing
172 | }
173 | dismiss();
174 | }
175 |
176 | private void sendResult() {
177 | Fragment fragment = getParentFragment();
178 | if (fragment != null) {
179 | Intent intent = new Intent();
180 | intent.putExtra(EXTRA_VALUE_SOLID_HEADER, mSolidRowHeader);
181 | intent.putExtra(EXTRA_VALUE_HEADER_FIXED, mIsHeaderFixed);
182 | intent.putExtra(EXTRA_VALUE_RTL_DIRECTION, mIsRtlDirection);
183 | intent.putExtra(EXTRA_VALUE_DRAG_AND_DROP_ENABLED, mIsDragAndDropEnabled);
184 | fragment.onActivityResult(REQUEST_CODE_SETTINGS, Activity.RESULT_OK, intent);
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/ClosableUtil.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.Closeable;
6 |
7 | public class ClosableUtil {
8 | private static final String TAG = ClosableUtil.class.getSimpleName();
9 |
10 | private ClosableUtil() {
11 |
12 | }
13 |
14 | public static void closeWithoutException(Closeable closeable) {
15 | try {
16 | if (closeable != null) {
17 | closeable.close();
18 | }
19 | } catch (Exception e) {
20 | Log.e(TAG, e.getMessage());
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/CsvUtils.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | // http://www.mkyong.com/java/how-to-read-and-parse-csv-file-in-java/
7 | public class CsvUtils {
8 | private static final char DEFAULT_SEPARATOR = ',';
9 | private static final char DEFAULT_QUOTE = '"';
10 | private CsvUtils() {
11 |
12 | }
13 |
14 | public static List parseLine(String cvsLine) {
15 | return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
16 | }
17 |
18 | public static List parseLine(String cvsLine, char separators) {
19 | return parseLine(cvsLine, separators, DEFAULT_QUOTE);
20 | }
21 |
22 | public static List parseLine(String cvsLine, char separators, char customQuote) {
23 |
24 | List result = new ArrayList<>();
25 |
26 | //if empty, return!
27 | if (cvsLine == null || cvsLine.isEmpty()) {
28 | return result;
29 | }
30 |
31 | if (customQuote == ' ') {
32 | customQuote = DEFAULT_QUOTE;
33 | }
34 |
35 | if (separators == ' ') {
36 | separators = DEFAULT_SEPARATOR;
37 | }
38 |
39 | StringBuffer curVal = new StringBuffer();
40 | boolean inQuotes = false;
41 | boolean startCollectChar = false;
42 | boolean doubleQuotesInColumn = false;
43 |
44 | char[] chars = cvsLine.toCharArray();
45 |
46 | for (char ch : chars) {
47 |
48 | if (inQuotes) {
49 | startCollectChar = true;
50 | if (ch == customQuote) {
51 | inQuotes = false;
52 | doubleQuotesInColumn = false;
53 | } else {
54 |
55 | //Fixed : allow "" in custom quote enclosed
56 | if (ch == '\"') {
57 | if (!doubleQuotesInColumn) {
58 | curVal.append(ch);
59 | doubleQuotesInColumn = true;
60 | }
61 | } else {
62 | curVal.append(ch);
63 | }
64 |
65 | }
66 | } else {
67 | if (ch == customQuote) {
68 |
69 | inQuotes = true;
70 |
71 | //Fixed : allow "" in empty quote enclosed
72 | if (chars[0] != '"' && customQuote == '\"') {
73 | // curVal.append('"');
74 | }
75 |
76 | //double quotes in column will hit this!
77 | if (startCollectChar) {
78 | curVal.append('"');
79 | }
80 |
81 | } else if (ch == separators) {
82 |
83 | result.add(curVal.toString());
84 |
85 | curVal = new StringBuffer();
86 | startCollectChar = false;
87 |
88 | } else if (ch == '\r') {
89 | //ignore LF characters
90 | continue;
91 | } else if (ch == '\n') {
92 | //the end, break!
93 | break;
94 | } else {
95 | curVal.append(ch);
96 | }
97 | }
98 |
99 | }
100 |
101 | result.add(curVal.toString());
102 |
103 | return result;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.OutputStream;
11 | import java.text.SimpleDateFormat;
12 | import java.util.Date;
13 | import java.util.Locale;
14 |
15 | public class FileUtils {
16 | private static final String PREFIX = "TEMP_";
17 | private static final String EXTENSION = ".csv";
18 |
19 | public static void copy(File src, File dst) throws IOException {
20 | InputStream in = new FileInputStream(src);
21 | OutputStream out = new FileOutputStream(dst);
22 |
23 | // Transfer bytes from in to out
24 | byte[] buf = new byte[1024];
25 | int len;
26 | while ((len = in.read(buf)) > 0) {
27 | out.write(buf, 0, len);
28 | }
29 | in.close();
30 | out.close();
31 | }
32 |
33 | public static void copy(InputStream in, File dst) throws IOException {
34 | OutputStream out = new FileOutputStream(dst);
35 |
36 | // Transfer bytes from in to out
37 | byte[] buf = new byte[1024];
38 | int len;
39 | while ((len = in.read(buf)) > 0) {
40 | out.write(buf, 0, len);
41 | }
42 | out.close();
43 | }
44 |
45 |
46 | /**
47 | * Create temp file file.
48 | *
49 | * @param context the context
50 | * @return the file
51 | */
52 | @SuppressWarnings("ResultOfMethodCallIgnored, unused")
53 | public static File createTempFile(Context context) {
54 | String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US).format(new Date());
55 | String tempFileName = PREFIX + timeStamp + "_";
56 | File cacheDir = context.getCacheDir();
57 | if (!cacheDir.exists()) {
58 | cacheDir.mkdir();
59 | }
60 | return new File(cacheDir, tempFileName + EXTENSION);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/PermissionHelper.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.pm.PackageManager;
6 | import android.support.annotation.NonNull;
7 | import android.support.v4.app.ActivityCompat;
8 | import android.support.v4.app.Fragment;
9 | import android.support.v4.content.ContextCompat;
10 |
11 | public class PermissionHelper {
12 | private PermissionHelper() {
13 |
14 | }
15 |
16 | /**
17 | * @return true if all permissions is granted
18 | */
19 | public static boolean check(@NonNull Context context, String... permissions) {
20 | boolean result = true;
21 | for (String permission : permissions) {
22 | result = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
23 | if (!result) {
24 | break;
25 | }
26 | }
27 | return result;
28 | }
29 |
30 | /**
31 | * @return true if all permissions is granted
32 | */
33 | public static boolean checkOrRequest(@NonNull Activity activity, int requestCode, String... permissions) {
34 | if (!check(activity, permissions)) {
35 | ActivityCompat.requestPermissions(activity, permissions, requestCode);
36 | return false;
37 | } else return true;
38 | }
39 |
40 | /**
41 | * @return true if all permissions is granted
42 | */
43 | public static boolean checkOrRequest(@NonNull Fragment fragment, int requestCode, String... permissions) {
44 | if (!check(fragment.getContext(), permissions)) {
45 | fragment.requestPermissions(permissions, requestCode);
46 | return false;
47 | } else return true;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/StringUtils.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | public class StringUtils {
4 | private StringUtils() {
5 |
6 | }
7 |
8 | public static String toString(Iterable iterable, String separator) {
9 | StringBuilder stringBuilder = new StringBuilder();
10 |
11 | for (Object item : iterable) {
12 | stringBuilder.append(String.valueOf(item));
13 | stringBuilder.append(separator);
14 | }
15 |
16 | if (stringBuilder.length() > 2) {
17 | return stringBuilder.substring(0, stringBuilder.length() - separator.length());
18 | } else return stringBuilder.toString();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/cleveroad/sample/utils/ValueInterpolator.java:
--------------------------------------------------------------------------------
1 | package com.cleveroad.sample.utils;
2 |
3 | public class ValueInterpolator {
4 | private float mRangeMapFromMin;
5 | private float mRangeMapToMin;
6 |
7 | private float mScaleFactor;
8 |
9 | public ValueInterpolator(float[] rangeMapFrom, float[] rangeMapTo) {
10 | this(rangeMapFrom[0], rangeMapFrom[1], rangeMapTo[0], rangeMapTo[1]);
11 | }
12 |
13 | public ValueInterpolator(float rangeMapFromMin, float rangeMapFromMax, float rangeMapToMin, float rangeMapToMax) {
14 | mRangeMapFromMin = rangeMapFromMin;
15 | mRangeMapToMin = rangeMapToMin;
16 |
17 | float rangeMapFromSpan = rangeMapFromMax - rangeMapFromMin;
18 | float rangeMapToSpan = rangeMapToMax - rangeMapToMin;
19 |
20 | mScaleFactor = rangeMapToSpan / rangeMapFromSpan;
21 | }
22 |
23 | public float map(float value) {
24 | return mRangeMapToMin + ((value - mRangeMapFromMin) * mScaleFactor);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/bg_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-hdpi/bg_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-hdpi/ic_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_csv_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-hdpi/ic_csv_new.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-hdpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-ldpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-ldpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/bg_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-mdpi/bg_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-mdpi/ic_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_csv_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-mdpi/ic_csv_new.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-mdpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/bg_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xhdpi/bg_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xhdpi/ic_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_csv_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xhdpi/ic_csv_new.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xhdpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/bg_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxhdpi/bg_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxhdpi/ic_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_csv_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxhdpi/ic_csv_new.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxhdpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/bg_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxxhdpi/bg_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_csv_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxxhdpi/ic_csv_file.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_csv_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxxhdpi/ic_csv_new.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/icon_csv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/drawable-xxxhdpi/icon_csv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/ic_arrow_back_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/ic_down_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/ic_up_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/separator_table_first.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/separator_table_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/separator_table_header_first.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/shadow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_add_column.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
19 |
20 |
28 |
29 |
38 |
39 |
47 |
48 |
55 |
56 |
63 |
64 |
65 |
75 |
76 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_add_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
19 |
20 |
28 |
29 |
38 |
39 |
47 |
48 |
55 |
56 |
63 |
64 |
65 |
75 |
76 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
19 |
20 |
27 |
28 |
38 |
39 |
47 |
48 |
55 |
56 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_edit_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
20 |
21 |
29 |
30 |
37 |
38 |
41 |
42 |
47 |
48 |
54 |
55 |
56 |
57 |
66 |
67 |
77 |
78 |
86 |
87 |
94 |
95 |
96 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_edit_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
19 |
20 |
28 |
29 |
35 |
36 |
41 |
42 |
43 |
44 |
50 |
51 |
58 |
59 |
60 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/dialog_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
20 |
21 |
29 |
30 |
37 |
38 |
39 |
42 |
43 |
51 |
52 |
61 |
62 |
71 |
72 |
81 |
82 |
90 |
91 |
98 |
99 |
100 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/fragment_csv_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
17 |
24 |
25 |
31 |
32 |
44 |
45 |
53 |
54 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/fragment_tab_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
25 |
26 |
32 |
33 |
40 |
41 |
47 |
48 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_body.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_header_column.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_header_left_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_header_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/table_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cleveroad/AdaptiveTableLayout/188213b35e05e635497b03fe741799782dde7208/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF394249
4 | #FF273238
5 | #FF394249
6 | #ffffffff
7 | #ffffffff
8 |
9 |
10 |
11 | #FF394249
12 | #FF273238
13 |
14 |
15 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 120dp
5 | 120dp
6 | 60dp
7 | 80dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | CSV Editor
4 |
5 | Add CSV table from your phone memory and you can read and edit it.
6 | Open any CSV or you can use this DEMO file
7 | Pick CSV-file
8 | Demo
9 |
10 | Edit song
11 | Settings
12 | Fixed headers
13 | Rtl direction
14 | Drag And Drop enabled
15 | Solid row
16 | Position
17 | Photo url
18 | Artist name
19 | Album name
20 | Song
21 | Genres
22 | Time
23 | WLS on chart
24 | Votes count
25 |
26 | Rock
27 | R&B
28 | Pop
29 | Jazz
30 | Hip hop
31 | Electronic
32 | Blues
33 | Country
34 |
35 |
36 | OK
37 | Cancel
38 |
39 | Artists
40 | Save
41 |
42 | All changes have been saved
43 | Unexpected error
44 | No such csv file
45 | Not csv file
46 | Delete row
47 | Add row
48 | Add row above
49 | Add row below
50 |
51 | This may take some time. Do you want to delete?
52 | Add column
53 | Delete column
54 | Add a column to the left
55 | Add a column to the right
56 | This may take some time.
57 |
58 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
19 |
20 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':library'
2 |
--------------------------------------------------------------------------------