Modify layout, activity_main.xml, to have a GridLayout without child.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.androidtouchview.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<GridLayout
android:id="@+id/mygrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:columnCount="8"
android:rowCount="5"
android:background="@android:color/background_light" >
</GridLayout>
</LinearLayout>
MyView.java
package com.example.androidtouchview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
public interface OnToggledListener {
void OnToggled(MyView v, boolean touchOn);
}
boolean touchOn;
boolean mDownTouch = false;
private OnToggledListener toggledListener;
int idX = 0; //default
int idY = 0; //default
public MyView(Context context, int x, int y) {
super(context);
idX = x;
idY = y;
init();
}
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(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);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
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 getIdX(){
return idX;
}
public int getIdY(){
return idY;
}
}
MainActivity.java
Our custom views, MyView, are created dynamically and add to the GridLayout in onCreate(). Then re-align their LayoutParams in OnGlobalLayoutListener(), will be called when the global layout state or the visibility of views within the view tree changes.
package com.example.androidtouchview;
import com.example.androidtouchview.MyView.OnToggledListener;
import android.support.v7.app.ActionBarActivity;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.GridLayout;
import android.widget.Toast;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity
implements OnToggledListener{
MyView[] myViews;
GridLayout myGridLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGridLayout = (GridLayout)findViewById(R.id.mygrid);
int numOfCol = myGridLayout.getColumnCount();
int numOfRow = myGridLayout.getRowCount();
myViews = new MyView[numOfCol*numOfRow];
for(int yPos=0; yPos<numOfRow; yPos++){
for(int xPos=0; xPos<numOfCol; xPos++){
MyView tView = new MyView(this, xPos, yPos);
tView.setOnToggledListener(this);
myViews[yPos*numOfCol + xPos] = tView;
myGridLayout.addView(tView);
}
}
myGridLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
final int MARGIN = 5;
int pWidth = myGridLayout.getWidth();
int pHeight = myGridLayout.getHeight();
int numOfCol = myGridLayout.getColumnCount();
int numOfRow = myGridLayout.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)myViews[yPos*numOfCol + xPos].getLayoutParams();
params.width = w - 2*MARGIN;
params.height = h - 2*MARGIN;
params.setMargins(MARGIN, MARGIN, MARGIN, MARGIN);
myViews[yPos*numOfCol + xPos].setLayoutParams(params);
}
}
}});
}
@Override
public void OnToggled(MyView v, boolean touchOn) {
//get the id string
String idString = v.getIdX() + ":" + v.getIdY();
Toast.makeText(MainActivity.this,
"Toogled:\n" +
idString + "\n" +
touchOn,
Toast.LENGTH_SHORT).show();
}
}
Download the files.
Notice:
- OnGlobalLayoutListener will be called repeatly this way. To remove it, call removeGlobalOnLayoutListener() or removeOnGlobalLayoutListener(), read next post.
Add some comments in codes explaining what is doing what.. Otherwise nice article in fact nice blog but having problem understanding few things, specially for person who coming from non programming background. Hope you will consider this.
ReplyDeletethank you :D
ReplyDeleteReally Thanks!!!!! Finally I can apply margins to textviews in gridlayout programmatically (not padding)
ReplyDeleteand I realize once again that I really hate this xxxx android API...
I misstyped the link of StackOverflow, that's it --> http://stackoverflow.com/questions/36063659/gridlayout-with-view-dynamic-get-row-column thanks a lot man...
ReplyDeletehow can we change color on finger move?
ReplyDelete