mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-01-30 17:13:50 +01:00
DroidFish: Use a specialized View class to speed up drawing of the move
list.
This commit is contained in:
parent
58e10bbc79
commit
39607ff9a4
|
@ -99,17 +99,13 @@
|
|||
android:layout_above="@+id/scrollViewBot"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<EditText
|
||||
<view
|
||||
class="org.petero.droidfish.MoveListView"
|
||||
android:id="@+id/moveList"
|
||||
android:tag="moveList"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="true"
|
||||
android:editable="false"
|
||||
android:padding="0dp"
|
||||
android:fontFamily="monospace"
|
||||
android:typeface="monospace"
|
||||
android:textSize="12sp"/>
|
||||
android:padding="0dp"/>
|
||||
</ScrollView>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -93,17 +93,13 @@
|
|||
android:layout_above="@+id/scrollViewBot"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<EditText
|
||||
<view
|
||||
class="org.petero.droidfish.MoveListView"
|
||||
android:id="@+id/moveList"
|
||||
android:tag="moveList"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="true"
|
||||
android:editable="false"
|
||||
android:padding="0dp"
|
||||
android:fontFamily="monospace"
|
||||
android:typeface="monospace"
|
||||
android:textSize="12sp"/>
|
||||
android:padding="0dp"/>
|
||||
</ScrollView>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -94,17 +94,13 @@
|
|||
android:layout_above="@+id/scrollViewBot"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<EditText
|
||||
<view
|
||||
class="org.petero.droidfish.MoveListView"
|
||||
android:id="@+id/moveList"
|
||||
android:tag="moveList"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:includeFontPadding="true"
|
||||
android:editable="false"
|
||||
android:padding="0dp"
|
||||
android:fontFamily="monospace"
|
||||
android:typeface="monospace"
|
||||
android:textSize="12sp"/>
|
||||
android:padding="0dp"/>
|
||||
</ScrollView>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
|
|
@ -104,13 +104,11 @@ import android.preference.PreferenceManager;
|
|||
import android.support.v4.view.MotionEventCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.text.Html;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
@ -139,7 +137,6 @@ import android.widget.ImageView.ScaleType;
|
|||
import android.widget.ListView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.BufferType;
|
||||
import android.widget.Toast;
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
|
@ -190,7 +187,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
|
||||
private TextView status;
|
||||
private ScrollView moveListScroll;
|
||||
private TextView moveList;
|
||||
private MoveListView moveList;
|
||||
private TextView thinking;
|
||||
private ImageButton custom1Button, custom2Button, custom3Button;
|
||||
private ImageButton modeButton, undoButton, redoButton;
|
||||
|
@ -242,7 +239,6 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
private boolean useWakeLock = false;
|
||||
|
||||
private Typeface figNotation;
|
||||
private Typeface defaultMoveListTypeFace;
|
||||
private Typeface defaultThinkingListTypeFace;
|
||||
|
||||
|
||||
|
@ -667,14 +663,12 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
|
||||
status = (TextView)findViewById(R.id.status);
|
||||
moveListScroll = (ScrollView)findViewById(R.id.scrollView);
|
||||
moveList = (TextView)findViewById(R.id.moveList);
|
||||
defaultMoveListTypeFace = moveList.getTypeface();
|
||||
moveList = (MoveListView)findViewById(R.id.moveList);
|
||||
thinking = (TextView)findViewById(R.id.thinking);
|
||||
defaultThinkingListTypeFace = thinking.getTypeface();
|
||||
status.setFocusable(false);
|
||||
moveListScroll.setFocusable(false);
|
||||
moveList.setFocusable(false);
|
||||
moveList.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
thinking.setFocusable(false);
|
||||
|
||||
initDrawers();
|
||||
|
@ -1029,8 +1023,6 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
if (config.orientation == Configuration.ORIENTATION_PORTRAIT)
|
||||
statusFontSize = Math.min(statusFontSize, 16);
|
||||
status.setTextSize(statusFontSize);
|
||||
moveList.setTextSize(fontSize);
|
||||
thinking.setTextSize(fontSize);
|
||||
soundEnabled = settings.getBoolean("soundEnabled", false);
|
||||
vibrateEnabled = settings.getBoolean("vibrateEnabled", false);
|
||||
animateMoves = settings.getBoolean("animateMoves", true);
|
||||
|
@ -1114,13 +1106,13 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
if (displayAsFigures) {
|
||||
// increase the font cause it has different kerning and looks small
|
||||
float increaseFontSize = fontSize * 1.1f;
|
||||
moveList.setTypeface(figNotation);
|
||||
moveList.setTextSize(increaseFontSize);
|
||||
moveList.setTypeface(figNotation, increaseFontSize);
|
||||
thinking.setTypeface(figNotation);
|
||||
thinking.setTextSize(increaseFontSize);
|
||||
} else {
|
||||
moveList.setTypeface(defaultMoveListTypeFace);
|
||||
moveList.setTypeface(null, fontSize);
|
||||
thinking.setTypeface(defaultThinkingListTypeFace);
|
||||
thinking.setTextSize(fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1717,12 +1709,11 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
|
||||
@Override
|
||||
public void moveListUpdated() {
|
||||
moveList.setText(gameTextListener.getSpannableData(), BufferType.SPANNABLE);
|
||||
Layout layout = moveList.getLayout();
|
||||
if (layout != null) {
|
||||
moveList.setText(gameTextListener.getText());
|
||||
int currPos = gameTextListener.getCurrPos();
|
||||
int line = layout.getLineForOffset(currPos);
|
||||
int y = (int) ((line - 1.5) * moveList.getLineHeight());
|
||||
int line = moveList.getLineForOffset(currPos);
|
||||
if (line >= 0) {
|
||||
int y = (line - 1) * moveList.getLineHeight();
|
||||
moveListScroll.scrollTo(0, y);
|
||||
}
|
||||
}
|
||||
|
@ -3562,7 +3553,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
this.options = options;
|
||||
}
|
||||
|
||||
public final SpannableStringBuilder getSpannableData() {
|
||||
public final CharSequence getText() {
|
||||
return sb;
|
||||
}
|
||||
public final int getCurrPos() {
|
||||
|
@ -3722,7 +3713,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
|
||||
@Override
|
||||
public void clear() {
|
||||
sb.clear();
|
||||
sb = new SpannableStringBuilder();
|
||||
prevType = PgnToken.EOF;
|
||||
nestLevel = 0;
|
||||
col0 = true;
|
||||
|
|
191
DroidFish/src/org/petero/droidfish/MoveListView.java
Normal file
191
DroidFish/src/org/petero/droidfish/MoveListView.java
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
DroidFish - An Android chess program.
|
||||
Copyright (C) 2015 Peter Österlund, peterosterlund2@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.petero.droidfish;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.Layout;
|
||||
import android.text.Layout.Alignment;
|
||||
import android.text.Spannable;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/** Custom view for displaying move list.
|
||||
* This is much faster than using a TextView. */
|
||||
public class MoveListView extends View {
|
||||
private CharSequence text = null;
|
||||
private Layout layout = null;
|
||||
private int layoutWidth = -1;
|
||||
private TextPaint textPaint;
|
||||
private Typeface defaultTypeface;
|
||||
|
||||
/** Constructor. */
|
||||
public MoveListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
textPaint.density = getResources().getDisplayMetrics().density;
|
||||
defaultTypeface = Typeface.create("monospace", Typeface.NORMAL);
|
||||
textPaint.setTypeface(defaultTypeface);
|
||||
}
|
||||
|
||||
/** Set text to display. */
|
||||
public void setText(CharSequence text) {
|
||||
if (text != this.text) {
|
||||
this.text = text;
|
||||
createLayout(getWidth());
|
||||
requestLayout();
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/** Set typeface and text size. If tf is null the default typeface is used. */
|
||||
public void setTypeface(Typeface tf, float size) {
|
||||
if (tf == null)
|
||||
tf = defaultTypeface;
|
||||
boolean modified = false;
|
||||
if (tf != textPaint.getTypeface()) {
|
||||
textPaint.setTypeface(tf);
|
||||
modified = true;
|
||||
}
|
||||
DisplayMetrics metric = getContext().getResources().getDisplayMetrics();
|
||||
size *= metric.scaledDensity;
|
||||
if (size != textPaint.getTextSize()) {
|
||||
textPaint.setTextSize(size);
|
||||
modified = true;
|
||||
}
|
||||
if (modified) {
|
||||
createLayout(getWidth());
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextColor(int color) {
|
||||
if (color != textPaint.getColor()) {
|
||||
textPaint.setColor(color);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/** Get line number corresponding to a character offset,
|
||||
* or -1 if layout has not been created yet. */
|
||||
public int getLineForOffset(int currPos) {
|
||||
if (layout == null)
|
||||
return -1;
|
||||
return layout.getLineForOffset(currPos);
|
||||
}
|
||||
|
||||
/** Get line height in pixels. */
|
||||
public int getLineHeight() {
|
||||
return textPaint.getFontMetricsInt(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int widthMeasure = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightMeasure = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
int width = getMeasuredWidth();
|
||||
switch (MeasureSpec.getMode(widthMeasureSpec)) {
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
break;
|
||||
case MeasureSpec.EXACTLY:
|
||||
width = widthMeasure;
|
||||
break;
|
||||
case MeasureSpec.AT_MOST:
|
||||
width = Math.min(width, widthMeasure);
|
||||
break;
|
||||
}
|
||||
|
||||
if (width != layoutWidth)
|
||||
createLayout(width);
|
||||
|
||||
int height = 0;
|
||||
if (layout != null)
|
||||
height = layout.getLineCount() * getLineHeight();
|
||||
switch (MeasureSpec.getMode(heightMeasureSpec)) {
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
break;
|
||||
case MeasureSpec.EXACTLY:
|
||||
height = heightMeasure;
|
||||
break;
|
||||
case MeasureSpec.AT_MOST:
|
||||
height = Math.min(height, heightMeasure);
|
||||
break;
|
||||
}
|
||||
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (layout != null) {
|
||||
canvas.save();
|
||||
canvas.translate(getPaddingLeft(), getPaddingTop());
|
||||
layout.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int action = event.getActionMasked();
|
||||
boolean ret = super.onTouchEvent(event);
|
||||
if ((action == MotionEvent.ACTION_UP) && (layout != null) &&
|
||||
(text instanceof Spannable)) {
|
||||
Spannable spannable = (Spannable)text;
|
||||
int x = (int)event.getX() - getPaddingLeft() + getScrollX();
|
||||
int y = (int)event.getY() - getPaddingTop() + getScrollY();
|
||||
int line = layout.getLineForVertical(y);
|
||||
int offs = layout.getOffsetForHorizontal(line, x);
|
||||
ClickableSpan[] link = spannable.getSpans(offs, offs, ClickableSpan.class);
|
||||
if (link.length > 0) {
|
||||
link[0].onClick(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Create a StaticLayout corresponding to the current text. */
|
||||
private void createLayout(int width) {
|
||||
if (width <= 0)
|
||||
return;
|
||||
if (text == null) {
|
||||
layout = null;
|
||||
layoutWidth = -1;
|
||||
} else {
|
||||
layout = new StaticLayout(text, textPaint, width,
|
||||
Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
|
||||
layoutWidth = width;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -121,7 +121,7 @@ public final class Util {
|
|||
final int bg = ColorTheme.instance().getColor(ColorTheme.GENERAL_BACKGROUND);
|
||||
Object tag = v.getTag();
|
||||
final boolean excludedItems = v instanceof Button ||
|
||||
((v instanceof EditText) && !"moveList".equals(tag)) ||
|
||||
((v instanceof EditText) && !(v instanceof MoveListView)) ||
|
||||
v instanceof ImageButton ||
|
||||
"title".equals(tag);
|
||||
if (!excludedItems) {
|
||||
|
@ -140,6 +140,9 @@ public final class Util {
|
|||
} else if (!excludedItems && (v instanceof TextView)) {
|
||||
int fg = ColorTheme.instance().getColor(ColorTheme.FONT_FOREGROUND);
|
||||
((TextView) v).setTextColor(fg);
|
||||
} else if (!excludedItems && (v instanceof MoveListView)) {
|
||||
int fg = ColorTheme.instance().getColor(ColorTheme.FONT_FOREGROUND);
|
||||
((MoveListView) v).setTextColor(fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user