I tried to create Grid Layout for this I used below code. But in that code I don't know what is ItemView and how to implement it. When I put this code in my project I get error can not resolve symbol "ItemView". I got this code from below link -
https://stackoverflow.com/a/36143314/5726392
public class PrivateSeatViews extends FrameLayout implements View.OnClickListener {
private GridLayout mGridView;
private int mRowsCount;
private int mColsCount;
private int mCellSpace;
private OnItemClickListener mOnItemClickListener;
public PrivateSeatViews(Context context) {
super(context);
init(context, null);
}
// other constructors
private void init(Context context, AttributeSet attrs) {
// default values
View layout = inflate(getContext(), R.layout.grid_layout, null);
mGridView = (GridLayout) layout.findViewById(R.id.Lower);
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
mGridView.post(new Runnable() {
#Override
public void run() {
int width = getMeasuredWidth() / getColumnsCount();
int height = getMeasuredHeight() / getRowsCount();
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
GridLayout.LayoutParams params = (GridLayout.LayoutParams) getChildAt(i, j).getL;
params.width = width;
params.height = height;
getChildAt(i, j).setLayoutParams(params);
}
}
}
});
addView(layout);
}
// this method allows to dinamically create grid
public void buildChildren(int rowsCount, int colsCount) {
mRowsCount = rowsCount;
mColsCount = colsCount;
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
buildChildren();
}
public void buildChildren() {
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
ItemView1 view = new ItemView1(getContext(), i, j);
view.setOnClickListener(this);
mGridView.addView(view);
}
}
}
public void setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
}
public ItemView getChildAt(int rowIndex, int columnIndex) {
int index = (getColumnsCount() * rowIndex) + columnIndex;
return (ItemView) mGridView.getChildAt(index);
}
public boolean isTouchOn(int rowIndex, int columnIndex) {
return getChildAt(rowIndex, columnIndex).isTouchOn();
}
public int getColumnsCount() {
return mGridView.getColumnCount();
}
public int getRowsCount() {
return mGridView.getRowCount();
}
#Override
public void onClick(View v) {
if (v instanceof ItemView) {
ItemView view = (ItemView) v;
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view);
}
}
}
public interface OnItemClickListener {
void onItemClick(ItemView view);
}
}
The best way i found to create the GridView is to use RecyclerView with the GridLayouy manager. Adapter implementations is the same as for normal RecyclerView
You can create GridLayout manager like this
//3 is the row span
GridLayoutManager a = new GridLayoutManager(this, 3);
This will help you to improve performance and create your view with the ViewHolder pattern
If you never used RecyclerView you can see a fine example here
Related
I have RecyclerView item decoration and add my RecyclerView. RecyclerView divider lost when change item background color.
My RecyclerView with divider:
When RecyclerView items selected, not show divider:
setBackgroundColor:
private void setBackgroundColor() {
if (selectedItem.isEmpty() || !selectedItem.contains(item)) {
this.setBackgroundColor(Color.TRANSPARENT);
} else {
this.setBackgroundColor(0xffffedc7);
}
}
DividerItemDecoration:
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public DividerItemDecoration(int resId) {
mDivider = ContextCompat.getDrawable(MyApplication.getContext(), resId);
}
#Override
public void onDraw(#NonNull Canvas canvas, RecyclerView parent, #NonNull RecyclerView.State state) {
int left = MyApplication.getContext().getResources().getDimensionPixelSize(R.dimen.profileImageSizeDivider);
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
}
}
Try this:
/**
* Draws left or right inset dividers at the bottom of every recycler item view. Only supports
* vertical orientations.
*/
public class InsetDividerItemDecoration extends RecyclerView.ItemDecoration {
private int mLeftInset = 0;
private int mRightInset = 0;
private int mStartPosition = 0;
final private Paint mLinePaint = new Paint();
final private List<Integer> mPositionsToIgnore = new ArrayList<>();
public InsetDividerItemDecoration(int leftInset, int rightInset, int dividerColor) {
mLeftInset = leftInset;
mRightInset = rightInset;
setColor(dividerColor);
}
public InsetDividerItemDecoration(int leftInset, int rightInset, int dividerColor, int startPosition) {
mLeftInset = leftInset;
mRightInset = rightInset;
mStartPosition = startPosition;
setColor(dividerColor);
}
public InsetDividerItemDecoration(int leftInset, int rightInset, int dividerColor, int startPosition, int dividerHeight) {
mLeftInset = leftInset;
mRightInset = rightInset;
mStartPosition = startPosition;
setColor(dividerColor);
setDividerHeight(dividerHeight);
}
public InsetDividerItemDecoration(int leftInset, int rightInset) {
this(leftInset, rightInset, 0);
}
public int getColor() {
return mLinePaint.getColor();
}
public void setColor(int color) {
mLinePaint.setColor(color);
}
public int getLeftInset() {
return mLeftInset;
}
public void setLeftInset(int leftInset) {
mLeftInset = leftInset;
}
public int getRightInset() {
return mRightInset;
}
public void setRightInset(int rightInset) {
mRightInset = rightInset;
}
public void setDividerHeight(int height) {
mLinePaint.setStrokeWidth(height);
}
public int getDividerHeight() {
return (int) mLinePaint.getStrokeWidth();
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
final int visibleItems = parent.getLayoutManager().getChildCount();
for (int i = 0; i < visibleItems; i++) {
View itemView = parent.getLayoutManager().getChildAt(i);
final int adapterPosition = parent.getChildAdapterPosition(itemView);
final boolean shouldDraw = adapterPosition != RecyclerView.NO_POSITION
&& adapterPosition != parent.getAdapter().getItemCount() - 1
&& adapterPosition >= mStartPosition
&& !shouldIgnoreAdapterPosition(adapterPosition);
if (shouldDraw) {
Rect itemRect = new Rect();
itemView.getDrawingRect(itemRect);
parent.offsetDescendantRectToMyCoords(itemView, itemRect);
final int lineStartX = mLeftInset;
final int lineStartY = itemRect.bottom;
final int lineEndX = itemRect.right - mRightInset;
final int lineEndY = lineStartY;
c.drawLine(lineStartX, lineStartY, lineEndX, lineEndY, mLinePaint);
}
}
}
protected boolean shouldIgnoreAdapterPosition(int position) {
return mPositionsToIgnore.size() > 0 && mPositionsToIgnore.contains(position);
}
public void setStartPosition(int startPosition) {
mStartPosition = startPosition;
}
public void setPositionsToIgnore(List<Integer> positionsToIgnore) {
mPositionsToIgnore.clear();
if (positionsToIgnore != null) {
mPositionsToIgnore.addAll(positionsToIgnore);
}
}
public void setPositionsToIgnore(Integer[] positionsToIgnore) {
setPositionsToIgnore(Arrays.asList(positionsToIgnore));
}
}
I have a list view where every item is a MPAndroidChart. The problem is that on the chart i set some gestures but when i try to perform these the list view intercept the gesture and perform the scroll.
Now i want to maintain the scroll of the list view but i want to perform the gesture on chart, how this is possible?
Also disable the scroll is useless because the list view anyway intercept the touch event and sto to perform the gesture on chart.
So what i want to do is to stop the list view to intercept the chart gesture but maintain the scroll of the list view
Class of the list view
public class ListViewMultiChartActivity extends DemoBase {
public static Button check_button, close_button;
public static LineChartItem chart;
public static ScatterChartItem chart2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_listview_chart);
check_button = (Button) findViewById(R.id.button);
close_button = (Button) findViewById(R.id.button2);
check_button.setVisibility(View.INVISIBLE);
close_button.setVisibility(View.INVISIBLE);
ListView lv = (ListView) findViewById(R.id.listView1);
ArrayList<ChartItem> list = new ArrayList<ChartItem>();
list.add(new LineChartItem(generateDataLine(0), getApplicationContext()));
list.add(new ScatterChartItem(generateDataScatter(1), getApplicationContext()));
ChartDataAdapter cda = new ChartDataAdapter(getApplicationContext(), list);
lv.setAdapter(cda);
chart = (LineChartItem) list.get(0);
chart2 = (ScatterChartItem) list.get(1);
check_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (chart.mChart.end_selection || chart2.mChart.end_selection) {
Highlight[] high;
if (chart.mChart.end_selection) {
high = chart.mChart.getHighlighted();
} else {
high = chart2.mChart.getHighlighted();
}
ArrayList<Entry> position;
ArrayList<Entry> position2;
LineDataSet d;
ScatterDataSet d2;
int i;
int j = 0;
int size = chart.mChart.getData().getDataSetCount();
while (j < size) {
i = 0;
position = new ArrayList<>();
position2 = new ArrayList<>();
while (i < high.length) {
int k = 0;
while (k < chart.mChart.getData().getDataSetByIndex(j).getEntryCount()) {
if (high[i].getX() == chart.mChart.getData().getDataSetByIndex(j).getEntryForIndex(k).getX() && j == high[i].getDataSetIndex()) {
position.add(chart.mChart.getData().getDataSetByIndex(j).getEntryForIndex(k));
position2.add(chart.mChart.getData().getDataSetByIndex(j).getEntryForIndex(k));
}
k++;
}
i++;
}
if (position.size() != 0) {
d = new LineDataSet(position, "Data" + j);
d.setLineWidth(2.5f);
d.setCircleRadius(4f);
int color = mColors[j % mColors.length];
d.setColor(color);
d.setCircleColor(color);
chart.mChart.getData().addDataSet(d);
d2 = new ScatterDataSet(position2, "Data" + j);
d2.setColor(color);
chart2.mChart.getData().addDataSet(d2);
}
j++;
}
i = 0;
while (i < size) {
chart.mChart.getData().removeDataSet(0);
chart2.mChart.getData().removeDataSet(0);
i++;
}
Highlight[] highvoid = new Highlight[0];
chart.mChart.highlightValues(highvoid);
chart2.mChart.highlightValues(highvoid);
chart.mChart.invalidate();
chart2.mChart.invalidate();
check_button.setVisibility(View.INVISIBLE);
close_button.setVisibility(View.INVISIBLE);
}
}
});
close_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (chart.mChart.end_selection || chart2.mChart.end_selection) {
Highlight[] high;
if (chart.mChart.end_selection) {
high = chart.mChart.getHighlighted();
} else {
high = chart2.mChart.getHighlighted();
}
int i = 0;
int j = 0;
while (i < high.length) {
j = 0;
while (j < chart.mChart.getData().getDataSetCount()) {
int k = 0;
while (k < chart.mChart.getData().getDataSetByIndex(j).getEntryCount()) {
if (high[i].getX() == chart.mChart.getData().getDataSetByIndex(j).getEntryForIndex(k).getX() && j == high[i].getDataSetIndex()) {
chart.mChart.getData().getDataSetByIndex(j).removeEntry(k);
chart2.mChart.getData().getDataSetByIndex(j).removeEntry(k);
}
k++;
}
j++;
}
i++;
}
Highlight[] highvoid = new Highlight[0];
chart.mChart.highlightValues(highvoid);
chart2.mChart.highlightValues(highvoid);
chart.mChart.invalidate();
chart2.mChart.invalidate();
check_button.setVisibility(View.INVISIBLE);
close_button.setVisibility(View.INVISIBLE);
}
}
});
}
/**
* adapter that supports 3 different item types
*/
private class ChartDataAdapter extends ArrayAdapter<ChartItem> {
public ChartDataAdapter(Context context, List<ChartItem> objects) {
super(context, 0, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).getView(position, convertView, getContext());
}
#Override
public int getItemViewType(int position) {
// return the views type
return getItem(position).getItemType();
}
#Override
public int getViewTypeCount() {
return 3; // we have 3 different item-types
}
}
/**
* generates a random ChartData object with just one DataSet
*
* #return
*/
private LineData generateDataLine(int cnt) {
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
ArrayList<Entry> values = new ArrayList<>();
for (int z = 0; z < 3; z++) {
values = new ArrayList<Entry>();
for (int i = 0; i < 20; i++) {
double val = (Math.random() * 100) + 3;
values.add(new Entry(i, (float) val));
}
LineDataSet d = new LineDataSet(values, "DataSet" + z);
d.setLineWidth(2.5f);
d.setCircleRadius(4f);
int color = mColors[z % mColors.length];
d.setColor(color);
d.setCircleColor(color);
dataSets.add(d);
}
LineData data = new LineData(dataSets);
return data;
}
/**
* generates a random ChartData object with just one DataSet
*
* #return
*/
private ScatterData generateDataScatter(int cnt) {
ArrayList<IScatterDataSet> dataSets = new ArrayList<IScatterDataSet>();
ArrayList<Entry> values = new ArrayList<>();
for (int z = 0; z < 3; z++) {
values = new ArrayList<Entry>();
for (int i = 0; i < 20; i++) {
double val = (Math.random() * 100) + 3;
values.add(new Entry(i, (float) val));
}
ScatterDataSet d = new ScatterDataSet(values, "DataSet" + z);
int color = mColors[z % mColors.length];
d.setColor(color);
dataSets.add(d);
}
ScatterData data = new ScatterData(dataSets);
return data;
}
private int[] mColors = new int[]{
ColorTemplate.VORDIPLOM_COLORS[0],
ColorTemplate.VORDIPLOM_COLORS[1],
ColorTemplate.VORDIPLOM_COLORS[2]
};
}
Abstact of the item of list view
public abstract class ChartItem {
protected static final int TYPE_BARCHART = 0;
protected static final int TYPE_LINECHART = 1;
protected static final int TYPE_PIECHART = 2;
protected static final int TYPE_SCATTERCHART = 3;
protected ChartData<?> mChartData;
public ChartItem(ChartData<?> cd) {
this.mChartData = cd;
}
public abstract int getItemType();
public abstract View getView(int position, View convertView, Context c);
}
Implementation of one of item of list view
public class ScatterChartItem extends ChartItem implements OnChartValueSelectedListener {
private Typeface mTf;
public ScatterChart mChart;
public ScatterChartItem(ChartData<?> cd, Context c) {
super(cd);
mTf = Typeface.createFromAsset(c.getAssets(), "OpenSans-Regular.ttf");
}
#Override
public int getItemType() {
return TYPE_SCATTERCHART;
}
#Override
public View getView(int position, View convertView, Context c) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(c).inflate(
R.layout.list_item_scatterchart, null);
holder.chart = (ScatterChart) convertView.findViewById(R.id.chart);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// apply styling
// holder.chart.setValueTypeface(mTf);
holder.chart.setDescription("");
holder.chart.setDrawGridBackground(false);
XAxis xAxis = holder.chart.getXAxis();
xAxis.setPosition(XAxisPosition.BOTTOM);
xAxis.setTypeface(mTf);
xAxis.setDrawGridLines(false);
xAxis.setDrawAxisLine(true);
YAxis leftAxis = holder.chart.getAxisLeft();
leftAxis.setTypeface(mTf);
leftAxis.setLabelCount(5, false);
leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
YAxis rightAxis = holder.chart.getAxisRight();
rightAxis.setTypeface(mTf);
rightAxis.setLabelCount(5, false);
rightAxis.setDrawGridLines(false);
rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)
// set data
holder.chart.setData((ScatterData) mChartData);
// do not forget to refresh the chart
// holder.chart.invalidate();
holder.chart.animateX(750);
holder.chart.setOnChartValueSelectedListener(this);
mChart=holder.chart;
return convertView;
}
#Override
public void onValueSelected(Entry e, Highlight h) {
}
#Override
public void onNothingSelected() {
}
#Override
public void onMultipleValueSelected() {
if (mChart.end_selection) {
Highlight[] high= mChart.getHighlighted();
ListViewMultiChartActivity.chart.mChart.highlightValues(high);
ListViewMultiChartActivity.check_button.setVisibility(View.VISIBLE);
ListViewMultiChartActivity.close_button.setVisibility(View.VISIBLE);
}else{
ListViewMultiChartActivity.check_button.setVisibility(View.INVISIBLE);
ListViewMultiChartActivity.close_button.setVisibility(View.INVISIBLE);
}
}
private static class ViewHolder {
ScatterChart chart;
}
}
I use the MPAndroidChart, here there is the class where i set the gesture of the chart
I just followed this tutorial, to create a custom View as an item of a GridLayout.
That's my CustomView
public class RowView extends View{
boolean touchOn;
boolean mDownTouch = false;
private OnToggledListener toggledListener;
int _IdRow = 0;
int _IdColumn = 0;
public RowView(Context context, int Rows, int Columns) {
super(context);
this._IdRow = Rows;
this._IdColumn = Columns;
init();
}
public RowView(Context context) {
super(context);
init();
}
public RowView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RowView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
touchOn = false;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
protected void onDraw(Canvas canvas) {
if (touchOn) {
canvas.drawColor(Color.RED);
} else {
canvas.drawColor(Color.GRAY);
}
}
//onClick not possible to use on custom View so, onTouchEvent is the solution
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
//if Click
case MotionEvent.ACTION_DOWN:
touchOn = !touchOn;
invalidate();
if(toggledListener != null){
toggledListener.OnToggled(this, touchOn);
}
mDownTouch = true;
return true;
case MotionEvent.ACTION_UP:
if (mDownTouch) {
mDownTouch = false;
performClick();
return true;
}
}
return false;
}
#Override
public boolean performClick() {
super.performClick();
return true;
}
public void setOnToggledListener(OnToggledListener listener){
toggledListener = listener;
}
public int get_IdRow() {
return _IdRow;
}
public int get_IdColumn() {
return _IdColumn;
}
On this class I can detect when user clicks on an item of GridLayout and change it to another color, that's ok.
But the problem comes at the time to create this :
This is my MainActivity where I show the GridLayout :
int numOfCol = mGridLayout.getColumnCount();
int numOfRow = mGridLayout.getRowCount();
mRowViews = new RowView[numOfCol*numOfRow];
for(int yPos=0; yPos<numOfRow; yPos++){
for(int xPos=0; xPos<numOfCol; xPos++){
RowView tView = new RowView(this, xPos, yPos);
tView.setOnToggledListener(this);
mRowViews[yPos*numOfCol + xPos] = tView;
mGridLayout.addView(tView);
}
}
mGridLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
#Override
public void onGlobalLayout() {
final int MARGIN = 5;
int pWidth = mGridLayout.getWidth();
int pHeight = mGridLayout.getHeight();
int numOfCol = mGridLayout.getColumnCount();
int numOfRow = mGridLayout.getRowCount();
int w = pWidth/numOfCol;
int h = pHeight/numOfRow;
for(int yPos=0; yPos<numOfRow; yPos++){
for(int xPos=0; xPos<numOfCol; xPos++){
GridLayout.LayoutParams params =
(GridLayout.LayoutParams)mRowViews[yPos*numOfCol + xPos].getLayoutParams();
params.width = w - 2*MARGIN;
params.height = h - 2*MARGIN;
params.setMargins(MARGIN, MARGIN, MARGIN, MARGIN);
mRowViews[yPos*numOfCol + xPos].setLayoutParams(params);
}
}
}});
Also there is a method of the Interface OnToggledListener that gives to me the row and column of my GridLayout when an item of it is clicked :
#Override
public void OnToggled(MyView v, boolean touchOn) {
//get the id string
String idString = v.get_IdRow() + ":" + v.get_IdColumn();
}
I'd like to avoid to create that mGridLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() because it fills on the screen thing that I don't want... I tried to put GridLayout 6x6 with android:layout_height="400dp" and it only show 3x3 and this is the LogCat message
D/android.widget.GridLayout: vertical constraints: y6-y0>=1749, y6-y5<=291, y5-y4<=291, y4-y3<=291, y3-y2<=291, y2-y1<=291, y1-y0<=291 are inconsistent; permanently removing: y6-y5<=291.
I'd like to do something like GridLayout[row][colum] to get the color of background and then do stuff, but I'm not able to find this solution.
For simplifying, you can implement a custom Board view wrapping the GridLayout and related logic. Below I report a possible approach.
Expectation here is to have an ItemView for representing one single cell in the board.
public class Board extends FrameLayout implements View.OnClickListener {
private GridLayout mGridView;
private int mRowsCount;
private int mColsCount;
private int mCellSpace;
private OnItemClickListener mOnItemClickListener;
public Board(Context context) {
super(context);
init(context, null);
}
// other constructors
private void init(Context context, AttributeSet attrs) {
// default values
mRowsCount = 1;
mColsCount = 1;
View layout = inflate(getContext(), R.layout.view_lights_board, null);
mGridView = (GridLayout) layout.findViewById(R.id.view_grid);
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
mGridView.post(new Runnable() {
#Override
public void run() {
int width = getMeasuredWidth() / getColumnsCount();
int height = getMeasuredHeight() / getRowsCount();
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
GridLayout.LayoutParams params = (GridLayout.LayoutParams)
getChildAt(i, j).getLayoutParams();
params.width = width;
params.height = height;
getChildAt(i, j).setLayoutParams(params);
}
}
}
});
addView(layout);
}
// this method allows to dinamically create grid
public void buildChildren(int rowsCount, int colsCount) {
mRowsCount = rowsCount;
mColsCount = colsCount;
mGridView.setRowCount(mRowsCount);
mGridView.setColumnCount(mColsCount);
buildChildren();
}
public void buildChildren() {
for (int i = 0; i < getRowsCount(); i++) {
for (int j = 0; j < getColumnsCount(); j++) {
ItemView view = new ItemView(getContext(), i, j);
view.setOnClickListener(this);
mGridView.addView(view);
}
}
}
public void setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
}
public ItemView getChildAt(int rowIndex, int columnIndex) {
int index = (getColumnsCount() * rowIndex) + columnIndex;
return (ItemView) mGridView.getChildAt(index);
}
public boolean isTouchOn(int rowIndex, int columnIndex) {
return getChildAt(rowIndex, columnIndex).isTouchOn();
}
public int getColumnsCount() {
return mGridView.getColumnCount();
}
public int getRowsCount() {
return mGridView.getRowCount();
}
#Override
public void onClick(View v) {
if (v instanceof ItemView) {
ItemView view = (ItemView) v;
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view);
}
}
}
public interface OnItemClickListener {
void onItemClick(ItemView view);
}
}
In your Activity layout you will have something like this (here I assume your app package is com.android.example):
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.android.example.Board
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="400dp" />
</FrameLayout>
And this is possible implementation of the Activity:
public class MainActivity extends AppCompatActivity implements LightsOutBoard.OnItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Board board = (Board) findViewById(R.id.grid);
board.setOnItemClickListener(this);
board.buildChildren(3, 3);
}
#Override
public void onItemClick(ItemView view) {
String text = view.getRowIndex() + " - " + view.getColumnIndex();
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
}
Hope this could help.
I want to achieve this layout. Table can have different number of rows, but once this number is set, it wouldn't change. Also, there is no need for scroll.
Well... I could do this with simple TableLayout, but it doesn't support data binding.
So I'm trying to implement custom AdapterView, but nothing is appeared in a screen.
public class MainActivity extends Activity {
String[][] data = new String[5][5];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_main, null);
setContentView(layout);
SquareTableView sqt = new SquareTableView(this);
sqt.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
sqt.setNumColumns(5);
layout.addView(sqt);
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++)
data[i][j] = "a";
sqt.setAdapter(new CellArrayAdapter(this, data) {
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
public class SquareTableView extends AdapterView<ListAdapter> {
private ListAdapter adapter;
private int numColumns;
public int getNumColumns() {
return numColumns;
}
public void setNumColumns(int numColumns) {
this.numColumns = numColumns;
}
public SquareTableView(Context context) {
super(context);
}
#Override
public ListAdapter getAdapter() {
return adapter;
}
#Override
public View getSelectedView() {
// TODO Auto-generated method stub
return null;
}
#Override
public void setAdapter(ListAdapter adapter) {
this.adapter = adapter;
requestLayout();
}
#Override
public void setSelection(int position) {
// TODO Auto-generated method stub
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Context context = getContext();
int orientation = context.getResources().getConfiguration().orientation;
int sideSize;
if (orientation == Configuration.ORIENTATION_PORTRAIT)
sideSize = MeasureSpec.getSize(widthMeasureSpec);
else {
sideSize = MeasureSpec.getSize(heightMeasureSpec);
}
setMeasuredDimension(sideSize, sideSize);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
for (int i = 0; i < adapter.getCount(); i++) {
int childSide = getWidth() / numColumns;
int row = i / numColumns;
int column = i % numColumns;
int leftPosition = childSide * column;
int rightPosition = leftPosition + childSide;
int topPosition = childSide * row;
int bottomPosition = topPosition + childSide;
View child = adapter.getView(i, null, this);
child.layout(leftPosition, topPosition, rightPosition, bottomPosition);
child.forceLayout();
}
}
I asked another questıon and after, I continued to this problem...
Firstly My first Question: how to Custom Button (has two TextFields) on Android
I extended a class form LinearLayout, and I add two buttons in it(width- fill_parent, weight-1).
But they can't place right. If I use LinearLayout insteadof my customClass, it is working right. What Should I do??
This is my class
public class SplitButtonController extends LinearLayout
implements
OnClickListener {
// Toggle buttons
private Vector<XButton2> buttons;
// Listener
private OnClickListener listener;
public SplitButtonController(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.xbutton2, this);
}
public SplitButtonController(Context context) {
super(context);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
init();
}
/**
* Initialize the toggle buttons (set images and listeners). It's
* responsibility of the user call this method after he add a ne
*/
public void init() {
buttons = new Vector<XButton2>();
addLayoutButtons();
changeButtonsImage();
setListeners();
}
private void addLayoutButtons() {
int n = getChildCount();
for (int i = 0; i < n; i++) {
View v = getChildAt(i);
if (v instanceof XButton2) {
buttons.add((XButton2) v);
}
}
}
private void changeButtonsImage() {
if (buttons.size() > 1) {
buttons.get(0)
.setBackgroundResource(
com.matriksdata.bavul.R.drawable.schedule_left_button_drawable);
for (int i = 1; i < buttons.size() - 1; i++) {
// buttons.get(i).setBackgroundResource(R.drawable.schedule_left_button_drawable);
}
buttons.get(buttons.size() - 1)
.setBackgroundResource(
com.matriksdata.bavul.R.drawable.schedule_right_button_drawable);
} else {
// TODO:set an image with rounded sides
}
}
private void setListeners() {
for (int i = 0; i < buttons.size(); i++) {
buttons.get(i).setOnClickListener(this);
buttons.get(i).setFocusable(true);
}
}
#Override
public void onClick(View v) {
for (int i = 0; i < buttons.size(); i++) {
XButton2 b = buttons.get(i);
b.setChecked(v == b);
}
}
}
The buttons you added to your SplitButtonController are XButton2, and in your constructor, you are inflating R.layout.xbutton2. This will cause an empty "XButton2" added to your SplitButtonController layout. You don't need to inflate anything if you want to create (or extend) a simple LinearLayout. Then your SplitButtonController code should look like following:
public class SplitButtonController extends LinearLayout
implements
OnClickListener {
// Toggle buttons
private Vector<XButton2> buttons;
// Listener
private OnClickListener listener;
public SplitButtonController(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
init();
}
/**
* Initialize the toggle buttons (set images and listeners). It's
* responsibility of the user call this method after he add a ne
*/
public void init() {
buttons = new Vector<XButton2>();
addLayoutButtons();
changeButtonsImage();
setListeners();
}
private void addLayoutButtons() {
int n = getChildCount();
for (int i = 0; i < n; i++) {
View v = getChildAt(i);
if (v instanceof XButton2) {
buttons.add((XButton2) v);
}
}
}
private void changeButtonsImage() {
if (buttons.size() > 1) {
buttons.get(0)
.setBackgroundResource(
com.matriksdata.bavul.R.drawable.schedule_left_button_drawable);
for (int i = 1; i < buttons.size() - 1; i++) {
// buttons.get(i).setBackgroundResource(R.drawable.schedule_left_button_drawable);
}
buttons.get(buttons.size() - 1)
.setBackgroundResource(
com.matriksdata.bavul.R.drawable.schedule_right_button_drawable);
} else {
// TODO:set an image with rounded sides
}
}
private void setListeners() {
for (int i = 0; i < buttons.size(); i++) {
buttons.get(i).setOnClickListener(this);
buttons.get(i).setFocusable(true);
}
}
#Override
public void onClick(View v) {
for (int i = 0; i < buttons.size(); i++) {
XButton2 b = buttons.get(i);
b.setChecked(v == b);
}
}
}