public class Table : View
{
private Paint p;//линия квадратиков
private Paint fill_p;//цвет подкрашенного квадратика
private Paint border_p;//граница видимой части канваса оранжевого цвета
private float scale_factor = 1.0f;//Скэйл Фактор для канваса
private readonly ScaleGestureDetector _scaleDetector;
private string debug_text;
private MotionEventActions last_action;
private float x;//точка касания, нужна для определения какой квадратик подсвечивать
private float y;
private float last_x;//предыдущие точки касания элемента, нужны для скрола
private float last_y;
private int margin = 50;
private int cols = 10;
private int rows = 10;
public Table (Context context) :
base (context)
{
Initialize ();
p = new Paint ();
p.Color = Color.White;
p.TextSize = 25;
fill_p = new Paint ();
fill_p.SetStyle (Paint.Style.Fill);
fill_p.Color = new Color(223, 136, 2);
border_p = new Paint ();
border_p.SetStyle (Paint.Style.Stroke);
border_p.Color = new Color(223, 136, 2);
_scaleDetector = new ScaleGestureDetector(context, new MyScaleListener(this));
}
public override bool OnTouchEvent(MotionEvent ev)
{
_scaleDetector.OnTouchEvent (ev);
MotionEventActions action = ev.Action & MotionEventActions.Mask;
//int pointerIndex;
Console.WriteLine (action.ToString ());
switch (action) {
/*запоминаем, где человек нажал квадратик, если следующее действие будет Move, то скроллим поле.
Если следующее движение будет Up, то мы подсвечим квадратик.
*/
case MotionEventActions.Down:
last_x = ev.GetX ();
last_y = ev.GetY ();
break;
case MotionEventActions.Move:
/*Скроллим*/
float x1 = ev.GetX ();
float y1 = ev.GetY ();
float delta_x = -x1 + last_x;
float delta_y = -y1 + last_y;
this.ScrollBy ((int)delta_x, (int)delta_y);
Console.WriteLine ("scrollX = {0}, scrollY = {1}", this.ScrollX, this.ScrollY);
/*Проверяем чтобы нельзя было скролить дальше, чем надо*/
if (this.ScrollX < 0) {
this.ScrollX = 0;
}
if (this.ScrollY < 0) {
this.ScrollY = 0;
}
/*недопускаем, чтобы можно было перескролить вправо и вниз*/
int visible_width = margin * cols + 1;
int visible_height = margin * cols + 1;
visible_width = (int)(visible_width * scale_factor);
visible_height = (int)(visible_height * scale_factor);
int bound_x = (visible_width - this.LayoutParameters.Width);
int bound_y = (visible_height - this.LayoutParameters.Height);
Console.WriteLine ("visible_width = {0}", visible_width);
if (this.ScrollX > bound_x) {
this.ScrollX = bound_x;
}
if (this.ScrollY > bound_y) {
this.ScrollY = bound_y;
}
break;
/*Запоминаем координаты для подсвечивания нужного квадратика*/
case MotionEventActions.Up:
if (last_action == MotionEventActions.Down) {
x = (ev.GetX () + this.ScrollX) / scale_factor;
y = (ev.GetY () + this.ScrollY)/ scale_factor;
debug_text = String.Format ("x = {0}, y = {0}", x, y);
Console.WriteLine (debug_text);
Invalidate ();
}
break;
}
last_action = action;
last_x = ev.GetX();
last_y = ev.GetY();
return true;
}
protected override void OnDraw (Android.Graphics.Canvas canvas)
{
/*Рисуем поле*/
base.OnDraw (canvas);
canvas.Save();
/*сделал на всякий случай Смещение на 0, 0. Не помогло*/
canvas.Translate (0, 0);
/*Увеличиваем/уменьшаем*/
canvas.Scale (scale_factor, scale_factor);
/*Рисуем клетчатое поле*/
int height = rows * margin;
int width = cols * margin;
for (int i = 0; i < cols + 1; i++) {
canvas.DrawLine (i * margin, 0, i * margin, height, p);
}
for (int i = 0; i < rows + 1; i++) {
canvas.DrawLine (0, i * margin, width, i * margin, p);
}
/*Находим отступы сверху и сбоку, чтобы номера писать ровно по центру квадратика
так как буквы имеют одинаковую ширину вычисляем эти значения только для строки "00"*/
string text = "00";
Rect bounds = new Rect();
p.GetTextBounds (text, 0, text.Length, bounds);
int padding_x = (margin - bounds.Width ())/2;
int padding_y = (margin - bounds.Height ())/2;
/*Подсвечиваем выбранный квадратик*/
int x_int = (int) Math.Floor(x / margin);
int y_int = (int) Math.Floor(y / margin);
Console.WriteLine ("x_int = {0}, y_int = {0}", x_int, y_int);
canvas.DrawRect (new RectF (x_int * margin + 1, y_int * margin + 1, x_int * margin + margin - 1, y_int * margin + margin - 1), fill_p);
/*Рисуем номера*/
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
string number = ((i * 10) + j).ToString("D2");
canvas.DrawText (number, j * margin + padding_x, i * margin + margin - padding_y, p);
}
}
canvas.Restore();
/*Рисуем оранжевую рамку вокруг поля*/
canvas.DrawLine (0, 0, this.Width - 1 + this.ScrollX, 0, border_p);//-
canvas.DrawLine (0, 0, 0, this.Height + this.ScrollY, border_p);//|
canvas.DrawLine (this.Width - 1 + this.ScrollX, 0, this.Width - 1 + this.ScrollX, this.Height - 1 + this.ScrollY, border_p);// |
canvas.DrawLine (0, this.Height - 1 + this.ScrollY, this.Width - 1 + this.ScrollX, this.Height - 1 + this.ScrollY, border_p);//_
Console.WriteLine (scale_factor);
}
public Table (Context context, IAttributeSet attrs) :
base (context, attrs)
{
Initialize ();
}
public Table (Context context, IAttributeSet attrs, int defStyle) :
base (context, attrs, defStyle)
{
Initialize ();
}
void Initialize ()
{
}
//Обработчик щипка для Zoom'а
private class MyScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
{
private Table view;
public MyScaleListener(Table view)
{
this.view = view;
}
public override bool OnScale(ScaleGestureDetector detector)
{
view.scale_factor *= detector.ScaleFactor;
if (view.scale_factor > 5.0f)
{
view.scale_factor = 5.0f;
}
if (view.scale_factor < 0.1f)
{
view.scale_factor = 0.1f;
}
Console.WriteLine ("view.scale_factor = {0}", view.scale_factor);
view.Invalidate ();
view.RequestLayout ();
return true;
}
}
}