I am worked on Bus Ticket Booking Application. I write code for seat layout but seats display in one column. I don't know why only one column display. but I want to look like below image
code that i used
void prepareSeatChart() {
try {
RelativeLayout[] r = new RelativeLayout[]{(RelativeLayout) findViewById(R.id.lowerDeckRelativeLayout), (RelativeLayout) findViewById(R.id.upperDeckRelativeLayout)};
int i = this._cellWidth;
if (this._cellWidth < 1) {
int totalHorizontalMargin = getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin) * 2;
this._cellWidth = (getWindowManager().getDefaultDisplay().getWidth() - totalHorizontalMargin) / this._cols;
if (this._cols < 6) {
this._cellWidth = (getWindowManager().getDefaultDisplay().getWidth() - totalHorizontalMargin) / 6;
}
this._cellHeight = (this._cellWidth * 82) / Constants.AppCompatTheme_ratingBarStyle;
}
if (this._hasCompartments[0]) {
findViewById(R.id.lowerDeckLinearLayout).setVisibility(View.VISIBLE);
findViewById(R.id.upperDeckLinearLayout).setVisibility(View.GONE);
findViewById(R.id.lowerDeckRelativeLayout).setVisibility(View.GONE);
findViewById(R.id.upperDeckRelativeLayout).setVisibility(View.GONE);
} else {
findViewById(R.id.lowerDeckLinearLayout).setVisibility(View.GONE);
findViewById(R.id.upperDeckLinearLayout).setVisibility(View.GONE);
findViewById(R.id.lowerDeckRelativeLayout).setVisibility(View.VISIBLE);
findViewById(R.id.upperDeckRelativeLayout).setVisibility(View.GONE);
}
if (this._seatWidth == 0) {
this._seatWidth = ((r[0].getWidth() - 20 - this._margin * 2 * this._cols) / this._cols);
if (this._cols < 6) {
this._seatWidth = ((r[0].getWidth() - 20 - this._margin * 2 * 6) / 6);
}
}
int w1 = this._seatWidth;
View emptyView = new View(this);
emptyView.setId((((this._rows * 10) + Constants.AUTH_API_INVALID_CREDENTIALS) + this._cols) + 2);
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.drawable.steering_icon);
imageView.setScaleType(ScaleType.CENTER);
imageView.setId((((this._rows * 10) + Constants.AUTH_API_INVALID_CREDENTIALS) + this._cols) + 1);
int width = (this._cellWidth * 64) / Constants.AppCompatTheme_ratingBarStyle;
int height = (this._cellWidth * 72) / Constants.AppCompatTheme_ratingBarStyle;
int mLeft = (this._cellWidth * 21) / Constants.AppCompatTheme_ratingBarStyle;
int mRight = mLeft;
int mTop = (int) (((double) ((this._cellWidth * 5) / Constants.AppCompatTheme_ratingBarStyle)) * 1.5d);
int mBottom = mTop;
if (this._cellWidth != (width + mLeft) + mRight) {
width = (this._cellWidth + width) - ((width + mLeft) + mRight);
}
if (this._cellHeight != (height + mTop) + mBottom) {
height = (this._cellHeight + height) - ((height + mTop) + mBottom);
}
emptyView.setLayoutParams(new RelativeLayout.LayoutParams(this._cellWidth * (this._cols - 1), height));
r[0].addView(emptyView);
RelativeLayout.LayoutParams imageViewParams = new RelativeLayout.LayoutParams(width, height);
imageViewParams.setMargins(mLeft, mTop, 0, mBottom);
imageViewParams.addRule(10, -1);
imageViewParams.addRule(1, emptyView.getId());
imageView.setLayoutParams(imageViewParams);
r[0].addView(imageView);
for (int d = 0; d < 2; d++) {
if (!this._hasCompartments[d]) {
int i4 = 0;
while (true) {
if (i4 >= this._rows) {
break;
}
int j = 0;
while (true) {
if (j >= this._cols) {
break;
}
if (this._seat[d][i4][j] == null) {
PrivateBusSeatGeSe s = new PrivateBusSeatGeSe();
s.setDeck(d);
s.setSeatColumns(j);
s.setSeatRows(i4);
s.setID((((s.getDeck() * BaseActivity.RESULT_CODE_ERROR) + (s.getSeatRows() * 10)) + s.getSeatColumns()) + 1);
this._seat[d][i4][j] = s;
}
if ((((d * BaseActivity.RESULT_CODE_ERROR) + (i4 * 10)) + j) + 1 == this._seat[d][i4][j].getID()) {
Button button = new Button(this);
button.setTextColor(getResources().getColor(R.color.btn_text_shadow));
if (this._seat[d][i4][j].getSelected()) {
button.setText(this._seat[d][i4][j].getSeatNo());
}
button.setId(this._seat[d][i4][j].getID());
button.setBackgroundResource(getSeatBackGroundResource(d, i4, j));
if (this._seat[d][i4][j].getAvailable()) {
button.setTag(this._seat[d][i4][j].getSeatNo());
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramAnonymousView) {
try {
PrivateBusSeatLayout.this.onSeatButtonClick(paramAnonymousView);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
int w;
int h;
int mL;
int mR;
int mT;
int mB;
ViewGroup.MarginLayoutParams layoutParams;
if (this._seat[d][i4][j].getSeatWidth() == 2) {
w = (this._cellWidth * 154) / Constants.AppCompatTheme_ratingBarStyle;
h = (this._cellWidth * 54) / Constants.AppCompatTheme_ratingBarStyle;
mL = (this._cellWidth * 29) / Constants.AppCompatTheme_ratingBarStyle;
mR = mL;
mT = (this._cellWidth * 14) / Constants.AppCompatTheme_ratingBarStyle;
mB = mT;
if (this._cellWidth * 2 != (w + mL) + mR) {
w = ((this._cellWidth * 2) + w) - ((w + mL) + mR);
}
i = this._cellHeight;
if (this._cellHeight != (h + mT) + mB) {
h = (this._cellHeight + h) - ((h + mT) + mB);
}
layoutParams = new RelativeLayout.LayoutParams(w, h);
layoutParams.setMargins(mL, mT, mR, mB);
} else {
if (this._seat[d][i4][j].getSeatHeight() == 2) {
w = (this._cellWidth * 54) / Constants.AppCompatTheme_ratingBarStyle;
h = (this._cellWidth * 154) / Constants.AppCompatTheme_ratingBarStyle;
mL = (this._cellWidth * 26) / Constants.AppCompatTheme_ratingBarStyle;
mR = mL;
mT = (this._cellWidth * 5) / Constants.AppCompatTheme_ratingBarStyle;
mB = mT;
i = this._cellWidth;
if (this._cellWidth != (w + mL) + mR) {
w = (this._cellWidth + w) - ((w + mL) + mR);
}
if (this._cellHeight * 2 != (h + mT) + mB) {
h = ((this._cellHeight * 2) + h) - ((h + mT) + mB);
}
layoutParams = new RelativeLayout.LayoutParams(w, h);
layoutParams.setMargins(mL, mT, mR, mB);
} else {
w = (this._cellWidth * 64) / Constants.AppCompatTheme_ratingBarStyle;
h = (this._cellWidth * 72) / Constants.AppCompatTheme_ratingBarStyle;
mL = (this._cellWidth * 21) / Constants.AppCompatTheme_ratingBarStyle;
mR = mL;
mT = (this._cellWidth * 5) / Constants.AppCompatTheme_ratingBarStyle;
mB = mT;
i = this._cellWidth;
if (this._cellWidth != (w + mL) + mR) {
w = (this._cellWidth + w) - ((w + mL) + mR);
}
i = this._cellHeight;
if (this._cellHeight != (h + mT) + mB) {
h = (this._cellHeight + h) - ((h + mT) + mB);
}
layoutParams = new RelativeLayout.LayoutParams(w, h);
layoutParams.setMargins(mL, mT, mR, mB);
}
}
if (i4 == 0) {
if (d == 0) {
((RelativeLayout.LayoutParams) layoutParams).addRule(3, imageView.getId());
} else {
((RelativeLayout.LayoutParams) layoutParams).addRule(10, -1);
}
}
if (j == 0) {
((RelativeLayout.LayoutParams) layoutParams).addRule(9, -1);
}
if (i4 > 0) {
((RelativeLayout.LayoutParams) layoutParams).addRule(3, this._seat[d][i4 - 1][j].getID());
}
if (j > 0) {
((RelativeLayout.LayoutParams) layoutParams).addRule(1, this._seat[d][i4][j - 1].getID());
}
button.setPadding(0, 0, 0, 0);
((Button) button).setTextSize(10.0f);
button.setLayoutParams(layoutParams);
r[d].addView(button);
}
j++;
}
i4++;
}
} else {
prepareSeatChartWithCompartments(d);
}
}
}catch (Exception e)
{
e.printStackTrace();
}
}
void prepareSeatChartWithCompartments(int d) {
LinearLayout[] l = new LinearLayout[]{(LinearLayout) findViewById(R.id.lowerDeckLinearLayout), (LinearLayout) findViewById(R.id.upperDeckLinearLayout)};
int w = ((getWindowManager().getDefaultDisplay().getWidth() - (this._margin * 6)) - 10) / 6;
int seatCount = 0;
Log.d("prpeare compartments","" + this._seatList.size());
for (int i = 0; i < this._seatList.size(); i++) {
PrivateBusSeatGeSe s = this._seatList.get(i);
if (s.getDeck() == d) {
View v;
LinearLayout.LayoutParams params;
if (seatCount % 2 == 0 && seatCount > 0) {
v = new View(this);
v.setBackgroundColor(getResources().getColor(R.color.gray));
int width = s.getSeatWidth() * w;
params = new LinearLayout.LayoutParams(-1, 1);
params.setMargins(w, 4, 0, 4);
v.setPadding(0, 0, 0, 0);
v.setLayoutParams(params);
l[d].addView(v);
}
if (seatCount % 2 == 1) {
v = new View(this);
params = new LinearLayout.LayoutParams(s.getSeatWidth() * w, (s.getSeatHeight() * w) / 2);
params.setMargins(w, 0, 0, 0);
v.setPadding(0, 0, 0, 0);
v.setLayoutParams(params);
l[d].addView(v);
}
Button v2 = new Button(this);
v2.setTextColor(getResources().getColor(R.color.btn_text_shadow));
if (s.getSelected()) {
v2.setText(s.getSeatNo());
}
v2.setId(s.getID());
v2.setBackgroundResource(getSeatBackGroundResourceWithSeat(s));
params = new LinearLayout.LayoutParams(s.getSeatWidth() * w, s.getSeatHeight() * w);
if (s.getSeatWidth() == 2) {
params.setMargins((this._margin * 2) + w, this._margin, this._margin * 2, this._margin);
} else if (s.getSeatHeight() == 2) {
params.setMargins(this._margin + w, this._margin * 2, this._margin, this._margin * 2);
} else {
params.setMargins(this._margin + w, this._margin, this._margin, this._margin);
}
v2.setPadding(0, 0, 0, 0);
v2.setTextSize(10.0f);
v2.setLayoutParams(params);
if (s.getAvailable()) {
v2.setTag(s.getSeatNo());
v2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View paramAnonymousView)
{
try {
PrivateBusSeatLayout.this.onSeatButtonClick(paramAnonymousView);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
l[d].addView(v2);
seatCount++;
}
}
}
int getSeatBackGroundResourceWithSeat(PrivateBusSeatGeSe s) {
String seatTypeStr = "";
String seatDirectionStr = "";
String seatGenderStr = "";
String seatStatusStr = "";
if(!s.getEmpty())
{
if (s.getSleeper()) {
seatTypeStr = Constants.GA_PRODUCT_VARIANT_SLEEPER;
if (s.getSeatWidth() == 2) {
seatDirectionStr = "_h";
} else if (s.getSeatHeight() == 2) {
seatDirectionStr = "_v";
}
} else if (s.getSeatNo().trim().length() > 0) {
seatTypeStr = Constants.GA_PRODUCT_VARIANT_SEATER;
}
if (s.getSelected()) {
seatStatusStr = "_selected";
} else {
if (s.getAvailable()) {
seatStatusStr = "_available";
} else {
seatStatusStr = "_booked";
}
if (s.getLadies()) {
seatGenderStr = "_female";
} else {
seatGenderStr = "_male";
}
}
if (seatTypeStr.trim().length() > 0) {
return this._seatLegendMap.get("ico_" + seatTypeStr + seatStatusStr + seatGenderStr + seatDirectionStr);
}
if (this._emptyColomn == -1 && s.getSeatColumns() > 0 && s.getSeatColumns() < this._cols) {
this._emptyColomn = s.getSeatColumns();
}
}
return 0;
}
Related
I have a custom view named as HorizontalScaleView
public class HorizontalScaleView extends View {
private static float THICK_STROKE_WIDTH = 16.0f;
private static float THIN_STROKE_WIDTH = 8.0f;
private static float THINNER_STROKE_WIDTH = 4.0f;
private int mColorStartGradient;
private int mColorEndGradient;
private int mColorOptimum;
private int mColorLineGradientStart;
private int mColorLineGradientEnd;
private int mColorDarkerGrey;
private int mMaxOptimumValue = 1000;
private Paint mLinePaint;
private Paint mTargetPaint;
private int mWidth;
private int mHeight;
private int markerValue = 0;
private int targetValue = 700;
private int averageValue = -1;
private Drawable mMarkerDrawable;
private Drawable mTargetDrawable;
private Rect markerRect = new Rect();
private Rect targetRect = new Rect();
public HorizontalScaleView(Context context) {
super(context);
mColorStartGradient = ContextCompat.getColor(context, R.color.colorBackGradientStart);
mColorEndGradient = ContextCompat.getColor(context, R.color.score_maintain);
mColorOptimum = ContextCompat.getColor(context, R.color.score_maintain);
mColorDarkerGrey = ContextCompat.getColor(context, R.color.textColorDarkGrey);
init(context);
}
public HorizontalScaleView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray attributes = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.HorizontalScaleView,
0, 0);
try {
mColorStartGradient = attributes.getColor(R.styleable.HorizontalScaleView_color_back_gradient_start,
ContextCompat.getColor(context, R.color.colorBackGradientStart));
mColorEndGradient = attributes.getColor(R.styleable.HorizontalScaleView_color_back_gradient_end,
ContextCompat.getColor(context, R.color.score_maintain));
mColorOptimum = attributes.getColor(R.styleable.HorizontalScaleView_color_optimum,
ContextCompat.getColor(context, R.color.score_maintain));
mColorLineGradientStart = attributes.getColor(R.styleable.HorizontalScaleView_color_gradient_start,
ContextCompat.getColor(context, R.color.line_gradient_start));
mColorLineGradientEnd = attributes.getColor(R.styleable.HorizontalScaleView_color_gradient_end,
ContextCompat.getColor(context, R.color.line_gradient_end));
mColorDarkerGrey = attributes.getColor(R.styleable.HorizontalScaleView_color_marker,
ContextCompat.getColor(context, R.color.textColorDarkGrey));
mMaxOptimumValue = attributes.getInteger(R.styleable.HorizontalScaleView_max_optimum_value,
1000);
targetValue = attributes.getInteger(R.styleable.HorizontalScaleView_target_value,
0);
averageValue = attributes.getInteger(R.styleable.HorizontalScaleView_average_value,
-1);
} finally {
attributes.recycle();
}
init(context);
}
private void init(Context context) {
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setStrokeWidth(THINNER_STROKE_WIDTH);
mTargetPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTargetPaint.setStrokeWidth(THINNER_STROKE_WIDTH);
mTargetPaint.setColor(ContextCompat.getColor(context, android.R.color.black));
mMarkerDrawable = context.getDrawable(R.drawable.ic_marker);
mTargetDrawable = context.getDrawable(R.drawable.ic_arrow_drop_up_black);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mWidth = getWidth();
int gap = (mHeight * 10) / 100;
int sidePadding = 2 * gap;
mWidth -= 2 * sidePadding;
mLinePaint.setTextSize((mHeight * 15) / 100);
mTargetPaint.setTextSize((mHeight * 15) / 100);
float optimumStopX = mWidth + sidePadding;
THIN_STROKE_WIDTH = (mHeight * 25) / 1000;
THINNER_STROKE_WIDTH = (mHeight * 15) / 1000;
Shader shader = new LinearGradient(sidePadding, mHeight / 2, optimumStopX, mHeight / 2,
mColorLineGradientStart, mColorLineGradientEnd, Shader.TileMode.CLAMP);
mLinePaint.setShader(shader);
mLinePaint.setStrokeWidth(mHeight * 4 / 100);
canvas.drawLine(sidePadding, mHeight * 32 / 100, optimumStopX, mHeight * 32 / 100, mLinePaint);
mLinePaint.setShader(null);
//Drawing background Gradient
int gradientHeight = (mHeight * 16) / 100;
shader = new LinearGradient(0, gradientHeight, mWidth + sidePadding + THIN_STROKE_WIDTH, gradientHeight,
mColorStartGradient, mColorEndGradient, Shader.TileMode.CLAMP);
mLinePaint.setShader(shader);
mLinePaint.setStrokeWidth(mHeight * 32 / 100);
mLinePaint.setAlpha(30);
canvas.drawLine(0, gradientHeight, mWidth + sidePadding + THIN_STROKE_WIDTH, gradientHeight, mLinePaint);
mLinePaint.setShader(null);
int borderLineHeight = (mHeight * 5) / 100;
mLinePaint.setAlpha(0);
mLinePaint.setStrokeWidth(THIN_STROKE_WIDTH);
mLinePaint.setColor(mColorLineGradientEnd);
canvas.drawLine(optimumStopX, (mHeight * 32 / 100) - borderLineHeight, optimumStopX, (mHeight * 32 / 100) + borderLineHeight, mLinePaint);
mLinePaint.setColor(mColorLineGradientStart);
canvas.drawLine(sidePadding, (mHeight * 32 / 100) - borderLineHeight, sidePadding, (mHeight * 32 / 100) + borderLineHeight, mLinePaint);
// Drawing Grade i.e 0 ' 100 ' 200 ' 300 ....... 1000
int gradeWidth = (int) ((optimumStopX - sidePadding) / 10);
int gradePositionX = sidePadding;
int gradePositionY = (mHeight * 44) / 100;
int gradeHeight = (mHeight * 3) / 100;
int gradeTextHeight = (mHeight * 58) / 100;
mLinePaint.setStrokeWidth(THIN_STROKE_WIDTH);
mLinePaint.setTextSize((mHeight * 10) / 100);
canvas.drawText("0", gradePositionX, gradeTextHeight, mLinePaint);
for (int index = 1; index < 10; index++) {
gradePositionX += gradeWidth;
if (index % 2 == 0) {
mLinePaint.setStrokeWidth(THIN_STROKE_WIDTH);
canvas.drawLine(gradePositionX, gradePositionY - gradeHeight, gradePositionX,
gradePositionY + gradeHeight, mLinePaint);
if ((index * 100) != targetValue) {
mLinePaint.setStrokeWidth(THIN_STROKE_WIDTH);
canvas.drawText(String.valueOf(index * 100), gradePositionX - ((mHeight * 8) / 100), gradeTextHeight, mLinePaint);
}
} else {
mLinePaint.setStrokeWidth(THINNER_STROKE_WIDTH);
canvas.drawLine(gradePositionX, gradePositionY - gradeHeight, gradePositionX,
gradePositionY + gradeHeight, mLinePaint);
}
}
canvas.drawText("1000", optimumStopX - ((mHeight * 22) / 100), gradeTextHeight, mLinePaint);
//Drawing Current Position
int markerPositionX = (int) (((optimumStopX - sidePadding) / mMaxOptimumValue) * markerValue);
markerPositionX += sidePadding;
int markerPositionY = mHeight * 34 / 100;
int markerWidth = (mHeight * 5 / 100);
int markerHeight = (mHeight * 65 / 1000);
mMarkerDrawable.setTint(mColorDarkerGrey);
markerRect.set(markerPositionX - 2 * markerWidth, markerPositionY - (5 * markerHeight),
markerPositionX + 2 * markerWidth, markerPositionY - markerHeight);
mMarkerDrawable.setBounds(markerRect);
mMarkerDrawable.draw(canvas);
canvas.restore();
//Drawing Target Position
if (targetValue <= 0) {
return;
}
mTargetPaint.setColor(mColorOptimum);
mTargetPaint.setStrokeWidth(THIN_STROKE_WIDTH);
mTargetPaint.setTextSize(mHeight * 18 / 100);
int targetPositionX = (int) (((optimumStopX - sidePadding) / mMaxOptimumValue) * targetValue);
int targetPositionY = mHeight * 58 / 100;
targetPositionX += sidePadding;
int targetWidth = (mHeight * 5 / 100);
int targetHeight = (mHeight * 4 / 100);
targetRect.set(targetPositionX - 2 * targetWidth, targetPositionY - targetHeight,
targetPositionX + 2 * targetWidth, targetPositionY + (4 * targetHeight));
mTargetDrawable.setTint(mColorOptimum);
mTargetDrawable.setBounds(targetRect);
mTargetDrawable.draw(canvas);
canvas.drawText(String.valueOf(targetValue), targetPositionX - (mHeight * 15 / 100), (mHeight * 82) / 100, mTargetPaint);
mTargetPaint.setTextSize(mHeight * 10 / 100);
canvas.drawText("Target", targetPositionX - (mHeight * 14 / 100), (mHeight * 95) / 100, mTargetPaint);
//Drawing Average Value
if (averageValue <= 0) {
return;
}
mTargetPaint.setColor(mColorDarkerGrey);
mTargetPaint.setStrokeWidth(THIN_STROKE_WIDTH);
mTargetPaint.setTextSize(mHeight * 18 / 100);
int averageValuePosition = (int) (((optimumStopX - sidePadding) / mMaxOptimumValue) * averageValue);
averageValuePosition += sidePadding;
targetRect.set(averageValuePosition - 2 * targetWidth, targetPositionY - targetHeight,
averageValuePosition + 2 * targetWidth, targetPositionY + (4 * targetHeight));
mTargetDrawable.setBounds(targetRect);
mTargetDrawable.draw(canvas);
canvas.drawText(String.valueOf(averageValue), averageValuePosition - 65, (mHeight * 82) / 100, mTargetPaint);
mTargetPaint.setTextSize(mHeight * 10 / 100);
canvas.drawText("Average", averageValuePosition - 70, (mHeight * 95) / 100, mTargetPaint);
mTargetPaint.setColorFilter(null);
}
public void setMarkerValue(int markerValue) {
this.markerValue = markerValue;
invalidate();
requestLayout();
}
public void setTargetValue(int targetValue) {
this.targetValue = targetValue;
invalidate();
requestLayout();
}
}
I used it in one of my layout files:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="vertical">
<TextView
android:id="#+id/score_card_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="12dp"
android:layout_marginRight="16dp"
android:text="#string/dashboard_household_score_card_desc"
android:textColor="#color/textColorDarkGrey"
android:textSize="14sp" />
<TextView
android:id="#+id/score_card_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/score_card_desc"
android:layout_marginLeft="16dp"
android:layout_marginTop="-8dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="-8dp"
android:fontFamily="sans-serif-light"
android:textColor="#color/textColorDarkGrey"
android:textSize="100sp"
tools:text="655" />
<com.kroger.mobile.components.HorizontalScaleView
android:id="#+id/score_card_graph"
style="#style/HorizontalScaleView"
android:layout_width="400dp"
android:layout_height="120dp"
android:layout_below="#+id/score_card_score"
android:layout_centerHorizontal="true"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
app:max_optimum_value="1000"
app:target_value="#integer/dashboard_target" />
</RelativeLayout>
</layout>
Now I want to take screenshot of this layout programmatically without displaying it on the screen and then and share it
I use these functions to generate, store and share screenshot respectively
private Bitmap generateScreenShot(Household household) {
LayoutDashboardScreenShotBinding shareBinding =
DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.layout_dashboard_screen_shot, null, false);
shareBinding.scoreCardScore.setText(String.valueOf(household.overallScore));
shareBinding.scoreCardGraph.setMarkerValue(household.overallScore);
shareBinding.scoreCardGraph.setTargetValue(0);
View shareView = shareBinding.getRoot();
shareView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
shareView.layout(0, 0, shareView.getMeasuredWidth(), shareView.getMeasuredHeight());
Bitmap bitmap = Bitmap.createBitmap(shareView.getWidth(), shareView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
shareView.draw(canvas);
return bitmap;
}
public File storeScreenShot(Bitmap bm, String fileName){
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + DIRECTORY_PATH;
File dir = new File(dirPath);
if(dir.exists() || dir.mkdirs()) {
File file = new File(dirPath, fileName);
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
return file;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
private void shareImage(File file){
Context context = getContext();
if(context == null){
return;
}
Uri uri = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".provider", file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "");
intent.putExtra(Intent.EXTRA_STREAM, uri);
try {
startActivity(Intent.createChooser(intent, "Share Screenshot"));
} catch (ActivityNotFoundException e) {
Toast.makeText(context, "No App Available", Toast.LENGTH_SHORT).show();
}
}
What I expect to capture in that screenshot is:
But what I am getting is:
The custom view that I have in this layout is not showing up on the screenshot.
Maybe HorizontalScaleView.setMeasuredDimensions() is getting called with 0,0 because you did not handle the case of MeasureSpecs like UNSPECIFIED, which would have a getSize() of 0 :)
How can I get started filling up text similar to this screen? Should I use a Handler and delay every character?
The background is that I am coding a mini game for Android similar to the classic Moon Patrol and now I want to create bonus for completing a checkpoint.
You can find my beta in the appstore https://play.google.com/store/apps/details?id=dev.android.buggy It is currently named "Moon Buggy". The code is available on request, right now the repo is closed source.
I put a test checkpoint at checkpoint "C" to show what I try:
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class ParallaxView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
int bombed = 5;
boolean waitForTimer = false;
boolean waitForTimer2 = false;
boolean recent = true;
char checkpoint;
boolean checkp = true;
Rect fromRect1;
Rect toRect1;
Rect fromRect2;
Rect toRect2;
boolean incCheck = true;
boolean increment = false;
int numberOfshots = 1;
int[] missiles = new int[200];
int alienBombYDelta = 0;
int alienBombXDelta = 20;
int p = 7;
boolean started = false;
final int buggyXDisplacement = 50;
boolean buggyDown = false;
int jumpHeight = 0;
int xbuggy2 = 0;
boolean down2 = true;
long lastTurn2 = System.currentTimeMillis();
long lastTurn3 = System.currentTimeMillis();
boolean jump = false;
boolean shoot = false;
int index = 0;
int missileOffSetY = 0;
boolean alienReset = false;
int score = 0;
double buggyXDistance = 0;
double distanceDelta = 1.15;
double retardation = 0.5;
boolean alienFire = false;
List<Background> backgrounds;
int spacerocki, resID, explodeID, explodeID2, alienResID2;
private volatile boolean running;
private Thread gameThread = null;
Bitmap explode, buggy, alien, explode2, spacerock;
boolean alienexplode = false;
TextView tvId;
//Activity a;
// For drawing
private Paint paint;
private Canvas canvas;
private SurfaceHolder ourHolder;
// Holds a reference to the Activity
Context context;
// Control the fps
long fps = 60;
// Screen resolution
int screenWidth;
int screenHeight;
boolean bexplode = false;
boolean brake = false;
boolean scoring = false;
class BuggyExploded extends TimerTask {
public void run() {
//Log.d("## BuggyExploded", "## BuggyExploded timer task running after 2 seconds" + buggyXDistance);
//buggy = BitmapFactory.decodeResource(context.getResources(), context.getResources().getIdentifier("vehicle",
// "drawable", context.getPackageName()));
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
buggyXDistance = 0;
distanceDelta = 1.15;
retardation = 0.5;
jumpHeight = 0;
waitForTimer = false;
//canvas.drawBitmap(buggy, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
}
}
class SetRecent extends TimerTask {
public void run() {
recent = false;
}
}
class ResetCheckpoint extends TimerTask {
public void run() {
Background.checkpoint = 'A';
}
}
class SetAlienBombs extends TimerTask {
public void run() {
missileOffSetY = 0;
}
}
class AlienBombed extends TimerTask {
public void run() {
alienBombXDelta = 20;
alienBombYDelta = 0;
alienReset = false;
alienexplode = false;
waitForTimer2 = false;
}
}
public void surfaceCreated(SurfaceHolder holder) {
//Canvas c = getHolder().lockCanvas();
//draw();
//getHolder().unlockCanvasAndPost(c);
}
public void surfaceDestroyed(SurfaceHolder holder3) {
//Canvas c = getHolder().lockCanvas();
//draw();
//getHolder().unlockCanvasAndPost(c);
}
public void surfaceChanged(SurfaceHolder holder, int i1, int i2, int i3) {
//Canvas c = getHolder().lockCanvas();
//draw();
//getHolder().unlockCanvasAndPost(c);
}
private void update() {
// Update all the background positions
for (Background bg : backgrounds) {
bg.update(fps);
}
}
public ParallaxView(Context c, AttributeSet a) {
super(c, a);
this.context = c;
Background.checkpoint--;
this.screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
this.screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
// Initialize our drawing objects
ourHolder = getHolder();
paint = new Paint();
// Initialize our array list
backgrounds = new ArrayList<>();
//load the background data into the Background objects and
// place them in our GameObject arraylist
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"bg", 0, 120, 50));
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"grass", 70, 110, 200));
//To execute the task every second after 3 s.
//Log.d("Timer", "Timer ");
resID = context.getResources().getIdentifier("vehicle",
"drawable", context.getPackageName());
explodeID = context.getResources().getIdentifier("explode",
"drawable", context.getPackageName());
explodeID2 = context.getResources().getIdentifier("explode2",
"drawable", context.getPackageName());
spacerocki = context.getResources().getIdentifier("spacerock",
"drawable", context.getPackageName());
buggy = BitmapFactory.decodeResource(context.getResources(), resID);
explode = BitmapFactory.decodeResource(context.getResources(), explodeID);
explode2 = BitmapFactory.decodeResource(context.getResources(), explodeID2);
spacerock = BitmapFactory.decodeResource(context.getResources(), spacerocki);
alienResID2 = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
alien = BitmapFactory.decodeResource(context.getResources(), alienResID2);
//resume();
//pause();
//resume();
}
#Override
public void run() {
while (running) {
long startFrameTime = System.currentTimeMillis();
update();
if (alienBombXDelta > screenWidth - 250 || alienBombXDelta < 10) { // alien ship change direction
p = -p;
}
draw();
// Calculate the fps this frame
long timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
private void checkJump() {
if (System.currentTimeMillis() - lastTurn3 >= 650) { // 650 means how long the vehicle is in the air at a jump
// Change direction here
jump = false;
lastTurn3 = System.currentTimeMillis();
}
}
private void checkBuggyBombed(Bitmap b1, Bitmap b2, Bitmap explode) {
if (!recent && java.lang.Math.abs(((buggyXDisplacement + buggyXDistance) + b1.getWidth() / 2) - (alienBombXDelta + 10 + b2.getWidth() / 2)) < b1.getWidth() / 2 && java.lang.Math.abs((alienBombYDelta + screenHeight / 100 * 25 + 75 + missileOffSetY) - ((screenHeight * 0.3) - jumpHeight + b1.getHeight())) < 65) {
bombed--;
missileOffSetY = 0;
checkpoint = 'A';
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
recent = true;
waitForTimer = true;
new Timer().schedule(new BuggyExploded(), 2000);
new Timer().schedule(new SetRecent(), 10000);
new Timer().schedule(new ResetCheckpoint(), 1000);
} else {
canvas.drawText("●", alienBombXDelta + 10 + b2.getWidth() / 2, alienBombYDelta + screenHeight / 100 * 25 + 75 + missileOffSetY, paint);
missileOffSetY = missileOffSetY + 10;
}
}
private void makeShots(Bitmap b) {
for (int i1 = 0; i1 < numberOfshots; i1++) {
// if vertical missile hits alien
if (java.lang.Math.abs(alienBombXDelta + 10 - 185 - buggyXDistance) * 2 < (b.getWidth() + 60) && java.lang.Math.abs(alienBombYDelta + screenHeight / 100 * 25 - (screenHeight / 100 * 95 - missiles[i1] - xbuggy2)) * 2 < (b.getHeight() + 60)) {
missileOffSetY = 9999;
canvas.drawBitmap(explode2, alienBombXDelta + 10, alienBombYDelta + screenHeight / 100 * 25, paint);
new Timer().schedule(new AlienBombed(), 2000);
waitForTimer2 = true;
if (!alienexplode) {
changeText();
}
alienexplode = true;
}
if (shoot) {
canvas.drawText("o", (float) (missiles[i1] + buggyXDistance), (float) (screenHeight * 0.7) - jumpHeight, paint); // add to y the jump height
canvas.drawText("o", (float) (buggyXDistance + 185), screenHeight / 110 * 95 - missiles[i1] - xbuggy2, paint);
}
if (i1 == numberOfshots - 1 && missiles[i1] > screenWidth) {
if (numberOfshots > 0) numberOfshots--;
if (index > 0) index--;
}
}
}
private void updateDeltas() {
alienBombXDelta = alienBombXDelta + p;
if (!down2)
alienBombYDelta++;
else
alienBombYDelta--;
}
private void changeDirections() {
if (System.currentTimeMillis() - lastTurn2 >= 7000) {
// Change direction here
down2 = !down2;
lastTurn2 = System.currentTimeMillis();
}
}
private void controlVelocity() {
if (!brake && buggyXDistance > 0) buggyXDistance = buggyXDistance + distanceDelta;
else if (brake && buggyXDistance > 0) buggyXDistance = buggyXDistance - retardation;
}
TextView tvId1;
private void drawDetails() {
//draw a background color
}
private void makeShots() {
for (int n = 0; n < numberOfshots; n++)
missiles[n] = missiles[n] + 20;
}
public void changeText() {
if (scoring) {
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
score++;
String str = "Player 1 " + String.format("%06d", score);
// Stuff that updates the UI
tvId.setText(str);
scoring = false;
}
});
}
}
double lastTurn4 = System.currentTimeMillis();
private void checkFire() {
if (System.currentTimeMillis() - lastTurn4 >= 18500) { // 18500 means how often the alien fires
lastTurn4 = System.currentTimeMillis();
missileOffSetY = 0;
}
}
boolean checkpointComplete = false;
private void draw() {
if (ourHolder.getSurface().isValid()) {
//First we lock the area of memory we will be drawing to
canvas = ourHolder.lockCanvas();
if (checkpointComplete) {
canvas.drawColor(Color.BLACK);
paint.setTextSize(60);
paint.setColor(Color.argb(255, 255, 255, 255));
paint.setTextSize(60);
canvas.drawText("CHECKPOINT COMPLETE", (float) (screenWidth * 0.5), (float) (screenHeight * 0.45), paint);
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
checkpointComplete = false;
}
}, 3000);
}
});
} else {
if (bombed == 0) //GAME OVER
{
final int duration = Toast.LENGTH_SHORT;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
final Toast toast = Toast.makeText(context, "GAME OVER!\nScore: " + score, duration);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
bombed = 5;
score = 0;
}
}, 3000);
}
});
}
if (jump && jumpHeight < 250) {
jumpHeight = jumpHeight + 7;
} else if (jumpHeight > 0) {
jumpHeight = jumpHeight - 4;
}
if (shoot) {
xbuggy2 = xbuggy2 + 4;
}
checkFire();
checkJump();
// drawDetails();
if (canvas != null) canvas.drawColor(Color.argb(255, 0, 0, 0));
// Draw the background parallax
drawBackground(0);
// Draw the rest of the game
paint.setTextSize(60);
paint.setColor(Color.argb(255, 255, 255, 255));
checkBuggyBombed(buggy, alien, explode);
makeShots(alien);
changeDirections();
if (!waitForTimer2)
canvas.drawBitmap(alien, alienBombXDelta + 10, alienBombYDelta + screenHeight / 100 * 25, paint);
drawBackground(1);
// canvas.drawText("X", (float) (50 + buggyXDistance)+buggy.getWidth()/2, (float) (screenHeight * 0.3) - jumpHeight+buggy.getHeight(), paint);
paint.setTextSize(60);
canvas.drawText("A E J O T Z", (float) (screenWidth * 0.7), (float) (screenHeight * 0.15), paint);
// Prevent buggy from moving outside horizontal screen
if (!brake && buggyXDisplacement + buggyXDistance > screenWidth - buggy.getWidth() - 200)
buggyXDistance = screenWidth - buggy.getWidth() - 200;
//Log.d("buggyXDistance", "buggyXDistance " + buggyXDistance);
if (!waitForTimer)
canvas.drawBitmap(buggy, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
else if (bexplode)
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
int inc = 0;
for (int i = 0; i < bombed; i++) {
canvas.drawBitmap(Bitmap.createScaledBitmap(buggy, (int) (0.75 * (buggy.getWidth() / 3)), buggy.getHeight() / 3, false), inc, 100, paint);
inc = inc + buggy.getWidth() / 3;
}
makeShots();
updateDeltas();
controlVelocity();
}
ourHolder.unlockCanvasAndPost(canvas);
}
}
// Clean up our thread if the game is stopped
public void pause() {
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// Error
//e.printStackTrace();
}
}
// Make a new thread and start it
// Execution moves to our run method
public void resume() {
running = true;
gameThread = new Thread(this);
gameThread.start();
}
private void drawBackground(int position) {
// Make a copy of the relevant background
Background bg = backgrounds.get(position);
// define what portion of images to capture and
// what coordinates of screen to draw them at
// For the regular bitmap
fromRect1 = new Rect(0, 0, bg.width - bg.xClip, bg.height);
toRect1 = new Rect(bg.xClip, bg.startY, bg.width, bg.endY);
// For the reversed background
fromRect2 = new Rect(bg.width - bg.xClip, 0, bg.width, bg.height);
toRect2 = new Rect(0, bg.startY, bg.xClip, bg.endY);
// Log.d("### bg.xClip", "bg.xClip " + bg.xClip);
//draw the two background bitmaps
if (!bg.reversedFirst) {
if (canvas != null) canvas.drawBitmap(bg.bitmap, fromRect1, toRect1, paint);
if (canvas != null) canvas.drawBitmap(bg.bitmapReversed, fromRect2, toRect2, paint);
if (position == 1) { // && Background.count % 2 == 0) {
if (increment) Background.checkpoint++;
if (Background.checkpoint == 'C' && (buggyXDisplacement + buggyXDistance) < (bg.xClip) && java.lang.Math.abs((buggyXDisplacement + buggyXDistance) - (bg.xClip)) < buggy.getWidth()) { // && java.lang.Math.abs((alienBombYDelta + screenHeight / 100 * 25 + 75 + missileOffSetY) - ((screenHeight * 0.3) - jumpHeight )) < 65) {) checkpointComplete = true;
checkpointComplete=true;
}
increment = false;
if (bg.xClip == bg.width) increment = true;
if (canvas != null) canvas.drawBitmap(spacerock, fromRect1, toRect1, paint);
paint.setTextSize(160);
if (canvas != null)
canvas.drawText(Character.toString(Background.checkpoint), bg.xClip, (float) (bg.startY * 1.4), paint);
//increment checkpoint once per what? "Background.checkpoint++;"
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
tvId1.setText(Character.toString(Background.checkpoint));
}
});
if (!recent && (buggyXDisplacement + buggyXDistance) < (bg.xClip) && java.lang.Math.abs((screenHeight * 0.5) - jumpHeight - bg.startY) < 180 && java.lang.Math.abs((buggyXDisplacement + buggyXDistance) - (bg.xClip)) < buggy.getWidth()) { // && java.lang.Math.abs((alienBombYDelta + screenHeight / 100 * 25 + 75 + missileOffSetY) - ((screenHeight * 0.3) - jumpHeight )) < 65) {
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
// Background.checkpoint = 'A';
bombed--;
recent = true;
waitForTimer = true;
bexplode = true;
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
distanceDelta = 1.15;
retardation = 0.5;
jumpHeight = 0;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
waitForTimer = false;
buggyXDistance = 0;
}
}, 2000);
}
});
// new Timer().schedule(new BuggyExploded(), 2000);
new Timer().schedule(new SetRecent(), 10000);
new Timer().schedule(new ResetCheckpoint(), 1000);
}
}
} else {
canvas.drawBitmap(bg.bitmap, fromRect2, toRect2, paint);
canvas.drawBitmap(bg.bitmapReversed, fromRect1, toRect1, paint);
}
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
#Override
public boolean performClick() {
super.performClick();
launchMissile();
return true;
}
protected void launchMissile() {
missiles[index] = 350; // what does it do?
index++;
xbuggy2 = 0;
shoot = true;
}
// event listener for when the user touches the screen
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean gameOver = false;
//if (paused) {
// paused = false;
//}
int action = MotionEventCompat.getActionMasked(event);
int coordX = (int) event.getX();
int coordY = (int) event.getY();
//Log.d("coordY", "coordY " + coordY);
if (coordX < 220 && jumpHeight == 0 && action == MotionEvent.ACTION_MOVE) {
jump = true;
shoot = false;
lastTurn3 = System.currentTimeMillis();
return true; // do nothing
}
if (coordX > 219 && action == MotionEvent.ACTION_DOWN) {
numberOfshots++;
performClick();
return true;
}
return true;
}
}
[
2]: https://i.stack.imgur.com/3NAmp.gif
You can follow the below code
public void setText(final String s)
{
TextView tv= (TextView) tf.getView().findViewById(R.id.textview1);
final int[] i = new int[1];
i[0] = 0;
final int length = s.length();
final Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
char c= s.charAt(i[0]);
Log.d("Strange",""+c);
tv.append(String.valueOf(c));
i[0]++;
}
};
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
handler.sendEmptyMessage(0);
if (i[0] == length - 1) {
timer.cancel();
}
}
};
timer.schedule(timerTask, 1, 500);
}
Think this will help you for sure
I'm developing a game using SurfaceView which listens to touch events. The onTouchEvent method in SurfaceView works fine for many of the devices, but in some devices, sometimes it doesn't get called (Moto X Style is the one) and my app also stops responding.
I guess that this might be due to the overloading of main thread due to which onTouchEvent is starving.
Could some Android experts over here give me some tips to reduce the load on main thread if it's getting overloaded, or there might be some other reason which may cause this
The code is quite complex but still I'm posting some if you want to go through it
GameLoopThread
public class GameLoopThread extends Thread{
private GameView view;
// desired fps
private final static int MAX_FPS = 120;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
private boolean running = false;
public GameLoopThread(GameView view){
this.view = view;
}
public void setRunning(boolean running){
this.running = running;
}
public boolean isRunning() {
return running;
}
#Override
public void run() {
Canvas canvas;
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
beginTime = System.nanoTime();
framesSkipped = 0; // resetting the frames skipped
// update game state
// render state to the screen
// draws the canvas on the panel
this.view.draw(canvas);
// calculate how long did the cycle take
timeDiff = System.nanoTime() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff/1000000);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// update without rendering
// add frame period to check if in next frame
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
}
}
finally {
// in case of an exception the surface is not left in
// an inconsistent state
view.getHolder().unlockCanvasAndPost(canvas);
} // end finally
}
}
}
GameView
public class GameView extends SurfaceView {
ArrayList<Bitmap> circles = new ArrayList<>();
int color;
public static boolean isGameOver;
public GameLoopThread gameLoopThread;
Circle circle; // Code for Circle class is provided below
public static int score = 0;
public static int stars = 0;
final Handler handler = new Handler();
int remainingTime;
boolean oneTimeFlag;
Bitmap replay;
Bitmap home;
Bitmap star;
int highScore;
boolean isLeaving;
public GameView(Context context, ArrayList<Bitmap> circles, int color) {
super(context);
this.circles = circles;
this.color = color;
oneTimeFlag = true;
gameLoopThread = new GameLoopThread(GameView.this);
getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!gameLoopThread.isRunning()) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.setRunning(false);
gameLoopThread = new GameLoopThread(GameView.this);
}
});
initializeCircles();
if(!gameLoopThread.isRunning()) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
}
public void initializeCircles() {
ArrayList<String> numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
Random random = new Random();
int position = random.nextInt(4);
numbers.remove(color + "");
int p1 = position;
int r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1+"");
int r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
int r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
ArrayList<Bitmap> bitmaps = new ArrayList<>();
if(position == 0) {
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 1) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 2) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r3));
}
else {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
bitmaps.add(circles.get(color));
}
numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
position = random.nextInt(4);
numbers.remove(color + "");
r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1 + "");
r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
if(position == 0) {
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 1) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 2) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r3));
}
else {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
bitmaps.add(circles.get(color));
}
circle = new Circle(this, bitmaps, circles, p1, position, color, getContext());
}
#Override
public void draw(Canvas canvas) {
if(canvas != null) {
super.draw(canvas);
canvas.drawColor(Color.WHITE);
if(!isGameOver && timer != null)
stopTimerTask();
try {
circle.draw(canvas);
} catch (GameOverException e) {
isGameOver = true;
if(isLeaving)
gameOver(canvas);
else if(GameActivity.counter > 0) {
gameOver(canvas);
GameActivity.counter++;
} else {
if (oneTimeFlag) {
int size1 = 200 * GameActivity.SCREEN_HEIGHT / 1280;
int size2 = 125 * GameActivity.SCREEN_HEIGHT / 1280;
float ratio = (float) GameActivity.SCREEN_HEIGHT / 1280;
replay = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.replay, size1, size1);
home = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.home, size2, size2);
continueButton = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.button, (int) (540 * ratio), (int) (100 * ratio));
star = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.star1, (int) (220 * ratio), (int) (220 * ratio));
int w = (int) ((float) GameActivity.SCREEN_WIDTH * 0.9);
oneTimeFlag = false;
}
if (askPurchaseScreen == 2) {
gameOver(canvas);
} else {
canvas.drawColor(Circle.endColor);
}
}
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
circle.onTouch(x, y);
return true;
}
}
Circle
public class Circle {
int x;
int y1;
int y2;
public static float speedY1 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280;
public static float speedY2 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280;
ArrayList<Bitmap> bitmaps;
GameView gameView;
int p1; // Position of required circle in slot 1
int p2; // Position of required circle in slot 2
int color;
int tempColor;
int width;
Context context;
// Centers of required circle
float centerX1;
float centerX2;
float centerY1;
float centerY2;
ArrayList<Bitmap> circles = new ArrayList<>();
boolean touchedFirst;
boolean touchedSecond;
int count1 = 1; // Slot 1 circle radius animation
int count2 = 1; // Slot 2 circle radius animation
float tempSpeedY1;
float tempSpeedY2;
boolean stopY1;
boolean stopY2;
int barCounter = 1;
int loopCount = 0;
int endGameCount = 0; // Count to move circle upwards
double limit;
float endRadiusSpeed;
int endSlot; // Where you died
int endRadiusCount = 0; // Count to increase circle radius
int barEndCounter = 1;
final Handler handler = new Handler();
boolean exception;
public static int endColor;
public Circle(GameView gameView, ArrayList<Bitmap> bitmaps, ArrayList<Bitmap> circles, int p1, int p2, int color, Context context) {
this.gameView = gameView;
this.bitmaps = bitmaps;
this.circles = circles;
this.p1 = p1;
this.p2 = p2;
this.color = color;
this.context = context;
width = GameActivity.SCREEN_WIDTH / 4 - 10;
x = 10;
y1 = 0;
y2 = -(GameActivity.SCREEN_HEIGHT + width) / 2;
centerX1 = x + p1 * (10 + width) + width / 2;
centerY1 = y1 + width / 2;
centerX2 = x + p2 * (10 + width) + width / 2;
centerY2 = y2 + width / 2;
}
public void update() throws GameOverException {
y1+= speedY1;
y2+= speedY2;
centerY1+= speedY1;
centerY2+= speedY2;
float ratio = (float)GameActivity.SCREEN_HEIGHT/1280;
limit = width/(20*ratio);
if(y1 >= gameView.getHeight()) {
loopCount++;
if(touchedFirst)
touchedFirst = false;
else {
speedY1 = speedY2 = -(12.5f * ratio);
endColor = bitmaps.get(p1).getPixel(width/2, width/2);
endGameCount += 1;
endSlot = 1;
}
if(endGameCount == 0) {
if (stopY1) {
tempSpeedY1 = speedY1;
speedY1 = 0;
ArrayList<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
if (i != color)
numbers.add(i);
}
tempColor = numbers.get(new Random().nextInt(9));
}
y1 = -(gameView.getWidth() / 4 - 10);
count1 = 1;
setBitmaps(1);
}
}
else if(y2 >= gameView.getHeight()) {
loopCount++;
if(touchedSecond)
touchedSecond = false;
else {
speedY1 = speedY2 = -(12.5f * ratio);
endColor = bitmaps.get(p2 + 4
).getPixel(width/2, width/2);
endGameCount += 1;
endSlot = 2;
}
if(endGameCount == 0) {
if (stopY2) {
tempSpeedY2 = speedY2;
speedY2 = 0;
}
y2 = -(gameView.getWidth() / 4 - 10);
count2 = 1;
setBitmaps(2);
}
}
}
public void setBitmaps(int slot) {
ArrayList<String> numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
Random random = new Random();
int position = random.nextInt(4);
numbers.remove(color + "");
int r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1+"");
int r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
int r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
if(position == 0) {
bitmaps.set((slot - 1)*4, circles.get(color));
bitmaps.set((slot - 1)*4 + 1, circles.get(r1));
bitmaps.set((slot - 1)*4 + 2, circles.get(r2));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
}
else if(position == 1) {
bitmaps.set((slot - 1)*4, circles.get(r1));
bitmaps.set((slot - 1)*4 + 1, circles.get(color));
bitmaps.set((slot - 1)*4 + 2, circles.get(r2));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
}
else if(position == 2) {
bitmaps.set((slot - 1)*4, circles.get(r1));
bitmaps.set((slot - 1)*4 + 1, circles.get(r2));
bitmaps.set((slot - 1)*4 + 2, circles.get(color));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
} else {
bitmaps.set((slot - 1)*4,circles.get(r1));
bitmaps.set((slot - 1)*4 + 1,circles.get(r2));
bitmaps.set((slot - 1)*4 + 2,circles.get(r3));
bitmaps.set((slot - 1)*4 + 3,circles.get(color));
}
if(slot == 1) {
p1 = position;
centerX1 = x+position*(10 + width) + width/2;
centerY1 = y1 + width/2;
}
else if(slot == 2) {
p2 = position;
centerX2 = x+position*(10 + width) + width/2;
centerY2 = y2 + width/2;
}
}
public void onTouch(float X, float Y) {
int radius = (gameView.getWidth() / 4 - 10) / 2;
if(endGameCount == 0) {
if ((X >= centerX1 - radius) && (X <= centerX1 + radius) && (Y >= centerY1 - radius) && (Y <= centerY1 + radius)) {
GameView.score++;
touchedFirst = true;
centerX1 = centerY1 = -1;
if(p1 == (timerCount - 1) && timer != null && starSlot == 1) {
GameView.stars++;
starCollected = true;
timerCount = 0;
stopTimerTask(0);
}
} else if ((X >= centerX2 - radius) && (X <= centerX2 + radius) && (Y >= centerY2 - radius) && (Y <= centerY2 + radius)) {
GameView.score++;
touchedSecond = true;
centerX2 = centerY2 = -1;
if(p2 == (timerCount - 1) && timer != null && starSlot == 2) {
GameView.stars++;
starCollected = true;
timerCount = 0;
stopTimerTask(0);
}
} else {
endSlot = 0;
if ((Y >= centerY1 - radius) && (Y <= centerY1 + radius)) {
endSlot = 1;
if (X >= 10 && X <= 10 + 2 * radius) {
p1 = 0;
centerX1 = 10 + radius;
} else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) {
p1 = 1;
centerX1 = 20 + 3 * radius;
} else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) {
p1 = 2;
centerX1 = 30 + 5 * radius;
} else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) {
p1 = 3;
centerX1 = 40 + 2 * radius;
} else
endSlot = 0;
} else if ((Y >= centerY2 - radius) && (Y <= centerY2 + radius)) {
endSlot = 2;
if (X >= 10 && X <= 10 + 2 * radius) {
p2 = 0;
centerX2 = 10 + radius;
} else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) {
p2 = 1;
centerX2 = 20 + 3 * radius;
} else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) {
p2 = 2;
centerX2 = 30 + 5 * radius;
} else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) {
p2 = 3;
centerX2 = 40 + 2 * radius;
} else
endSlot = 0;
}
if (endSlot != 0) {
speedY1 = speedY2 = 0;
limit = endGameCount = 6;
if (endSlot == 1) {
endColor= bitmaps.get(p1).getPixel(width/2, width/2);
} else {
endColor = bitmaps.get(p2 + 4).getPixel(width/2, width/2);
}
}
}
if (GameView.score % 5 == 0 && GameView.score <= 110 && barCounter == 1) {
float ratio = (float)GameActivity.SCREEN_HEIGHT/1280;
speedY1 += ratio*0.5;
speedY2 += ratio*0.5;
}
if (GameView.score > 0 && GameView.score % 15 == 14) {
if(isOddScore)
stopY1 = true;
else
stopY2 = true;
}
if (GameView.score > 0 && GameView.score % 15 == 0 && barCounter == 1) {
if(isOddScore)
stopY2 = true;
else
stopY1 = true;
}
if (GameView.score % 15 == 1)
barCounter = 1;
}
}
public void draw(Canvas canvas) throws GameOverException {
GameView.isGameOver = false;
if(exception)
throw new GameOverException(color);
update();
for(int i=0;i<bitmaps.size();i++) {
if(i<4) {
Rect rect = new Rect(x+i*(10 + width),y1,(x+width)*(i+1),y1+width);
if(endGameCount == Math.ceil(limit) && endSlot == 1) {
if(i == p1) {
endRadiusCount += 1;
if (endRadiusCount > 23) {
star.recycle();
loopCount = loopCount%starInterval;
Cryptography.saveFile((loopCount + "").getBytes(), context, "interval");
endGameCount = 0;
exception = true;
throw new GameOverException(color);
}
rect = new Rect(x + i * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * (i + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
}
}
// TOUCH ANIMATION : DIMINISH CIRCLE
else if(i==p1 && touchedFirst) {
rect = new Rect(x + i * (10 + width) + 3*count1 + ((int)speedY1-15), y1 + 3*count1 + ((int)speedY1-15), (x + width) * (i + 1) - 3*count1 - ((int)speedY1-15), y1 + width - 3*count1 - ((int)speedY1-15));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
count1++;
}
else if(endSlot != 2) {
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
if(timerCount > 0 && starSlot == 1) {
int size = width * 30 / 50;
int difference = (width - size) / 2;
Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y1 + difference, (x + width) * (timerCount) - difference, y1 + width - difference);
canvas.drawBitmap(star, null, starRect, null);
}
}
}
if(i >= 4) {
Rect rect = new Rect(x + (i % 4) * (10 + width), y2, (x + width) * ((i % 4) + 1), y2 + width);
if(endGameCount == Math.ceil(limit) && endSlot == 2) {
if((i%4)==p2) {
endRadiusCount += 1;
if (endRadiusCount > 23) {
star.recycle();
loopCount = loopCount%starInterval;
Cryptography.saveFile((loopCount + "").getBytes(), context, "interval");
endGameCount = 0;
exception = true;
throw new GameOverException(color);
}
rect = new Rect(x + (i % 4) * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * ((i % 4) + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
}
}
else if((i%4)==p2 && touchedSecond) {
rect = new Rect(x + (i % 4) * (10 + width) + 3*count2 + ((int)speedY1-15), y2 + 3*count2 + ((int)speedY1-15), (x + width) * ((i % 4) + 1) - 3*count2 - ((int)speedY1-15), y2 + width - 3*count2 - ((int)speedY1-15));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
count2++;
}
else if(endSlot != 1) {
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
if(timerCount > 0 && starSlot == 2) {
int size = width * 30 / 50;
int difference = (width - size) / 2;
Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y2 + difference, (x + width) * (timerCount) - difference, y2 + width - difference);
canvas.drawBitmap(star, null, starRect, null);
}
}
}
}
Rect src = new Rect(circles.get(color).getWidth()/2 - 10,circles.get(color).getHeight()/2 - 10,circles.get(color).getWidth()/2 + 10,circles.get(color).getHeight()/2 + 10);
Rect dst;
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextAlign(Paint.Align.RIGHT);
paint.setTypeface(Typeface.SANS_SERIF);
paint.setTextSize(72 * ratio);
canvas.drawText(GameView.score + " ", GameActivity.SCREEN_WIDTH, width / 2, paint);
dst = new Rect(5,5, (int) (120 * ratio - 5), (int) (120 * ratio - 5));
canvas.drawBitmap(star,null,dst,null);
paint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("" + GameView.stars, 120 * ratio, width/2, paint);
}
}
Don't override draw(). That's used to render the View, not the Surface, and you generally shouldn't override that method even if you're creating a custom View:
When implementing a view, implement onDraw(android.graphics.Canvas) instead of overriding this method.
SurfaceViews have two parts, the Surface and the View. The View part is handled like any other View, but is generally just a transparent "hole" in the layout. The Surface is a separate layer that, by default, sits behind the View layer. Whatever you draw on the Surface "shows through" the transparent hole.
By overriding draw() you're drawing on the View whenever the View UI is invalidated. You're also calling draw() from the render thread, so you're drawing on the Surface, but with default Z-ordering you can't see that because the View contents are fully opaque. You will reduce your impact on the UI thread by not drawing everything in two different layers.
Unless you're deliberately drawing on the View, it's best to avoid subclassing SurfaceView entirely, and just use it as a member.
Because your draw code is synchronized, the two draw passes will not execute concurrently. That means your View layer draw call will block waiting for the Surface layer rendering to complete. Canvas rendering on a Surface is not hardware-accelerated, so if you're touching a lot of pixels it can get slow, and the UI thread will have to wait for it to run. That wouldn't be so bad, but you're holding on to the mutex while you're sleeping, which means the only opportunity for the main UI thread to run comes during the brief instant when the loop wraps around. The thread scheduler does not guarantee fairness, so it's entirely possible to starve the main UI thread this way.
If you change #override draw() to myDraw() things should get better. You should probably move your sleep call out of the synchronized block just on general principles, or work to eliminate it entirely. You might also want to consider using a custom View instead of SurfaceView.
On an unrelated note, you should probably avoid doing this every update:
Random random = new Random();
for the reasons noted here.
Successfully solved the issue. Can't imagine that the solution would be this much simple as compared to the problem that I was considering that complex. Just reduced the frame rate from 120 to 90 and guess what, it worked like charm!
Due to a high frame rate, the SurfaceView was busy doing all the drawing and onTouchEvent() method had to starve
I have problem, with rendering blocks after reScalling (zoom in-out) whole thing in my game
(sorry with my eng syntax , cuz Eng not my native language)
first look at my video
>Error Rendering Video
there are problem , When it's rendering blocks after change blocks scale to some specific number
look at my code
GameLoopThread.java
public class GameLoopThread extends Thread {
static long FPS = 20;
private GameView view;
private boolean running = false;
public GameLoopThread ( GameView view ) {
this.view = view;
}
#Override
public void run () {
long ticksPS = 1000 / GameLoopThread.FPS; // 0.05 second (50) ;
long startTime;
long delayDelta = 0;
long tmpDelta = 0;
while (this.running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = this.view.getHolder().lockCanvas();
synchronized (this.view.getHolder()) {
this.view.onDraw(c);
}
ClientCoreStatic.clientGear.updateWorlds();
}
catch (NullPointerException e) {
e.printStackTrace();
}
finally {
if (c != null) this.view.getHolder().unlockCanvasAndPost(c);
}
// 50
// sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
tmpDelta = (System.currentTimeMillis() - startTime);
// time use Should below than 50
try {
if (tmpDelta > ticksPS) delayDelta += tmpDelta - ticksPS;
// d.pl("gameloop thread + " + delayDelta);
if (delayDelta > 0) {
//Thread.sleep(10);
if (ticksPS >= tmpDelta) {
delayDelta -= ticksPS - tmpDelta;
}
}
else {
delayDelta = 0;
Thread.sleep(ticksPS - tmpDelta);
}
if (this.view.hashCode() != ClientStatic.gameView.hashCode()) {
this.setRunning(false);
GameView.parentActivity.finish();
break;
}
}
catch (Exception e) {
e.printStackTrace();
d.pl("gameloop error");
}
}
}
GameView.java
#Override
public boolean onTouchEvent ( MotionEvent event ) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// true
if (event.getPointerCount() == 1 ) {
if (GameView.spriteKeypadcircle.isCollition(
event.getX(),
event.getY()) == true) // d.pl("true..");
return true;
if (GameView.spriteBlocks.isCollition(event.getX(), event.getY())) {
// check
GameView.spriteBlocks.isCollitionOnBlock(event.getX(),event.getY());
d.pl("touching at "+ event.getX() + "," + event.getY());
return true;
}
}
if (event.getPointerCount() == 2 ) {
d.pl("distance 1 " +
GameView.distance1XY[0][0] +
"," +
GameView.distance1XY[0][1] +
" + " +
GameView.distance1XY[1][0] +
"," +
GameView.distance1XY[1][1] +
" | " +
GameView.distance2XY[0][0] +
"," +
GameView.distance2XY[0][1] +
" + " +
GameView.distance2XY[1][0] +
"," +
GameView.distance2XY[1][1]);
for (int size = event.getPointerCount(), i = 0; i < size; i++) {
// PointF point = mActivePointers.get(event.getPointerId(i));
// if (point != null) {
// point.x = event.getX(i);
// point.y = event.getY(i);
// }
float x = event.getX(i);
float y = event.getY(i);
if (!GameView.spriteBlocks.isCollition(x, y)) break;
GameView.distance2XY[i][0] = x;
GameView.distance2XY[i][1] = y;
} // for
// after get position
// check distance
double tmp1 = Math.sqrt((Math.pow(GameView.distance1XY[0][0] -
GameView.distance1XY[1][0], 2)) +
(Math.pow(GameView.distance1XY[0][1] -
GameView.distance1XY[1][1], 2)));
double tmp2 = Math.sqrt((Math.pow(GameView.distance2XY[0][0] -
GameView.distance2XY[1][0], 2)) +
(Math.pow(GameView.distance2XY[0][1] -
GameView.distance2XY[1][1], 2)));
GameView.newDistance = Math.abs(tmp1 - tmp2);
if (GameView.newDistance > 200) { // change too much
GameView.distance1XY[0][0] = GameView.distance2XY[0][0];
GameView.distance1XY[0][1] = GameView.distance2XY[0][1];
GameView.distance1XY[1][0] = GameView.distance2XY[1][0];
GameView.distance1XY[1][1] = GameView.distance2XY[1][1];
return true;
}
// if (newDistance < 100) break;
// if (newD < 100) break;
if (tmp1 < tmp2)
SpriteBlocks.viewScale += GameView.newDistance / 1000;
else
SpriteBlocks.viewScale -= GameView.newDistance / 1000;
if (SpriteBlocks.viewScale < 0.2) SpriteBlocks.viewScale = 0.2;
if (SpriteBlocks.viewScale > 10) SpriteBlocks.viewScale = 10;
GameView.spriteBlocks.updateScale();
GameView.distance1XY[0][0] = GameView.distance2XY[0][0];
GameView.distance1XY[0][1] = GameView.distance2XY[0][1];
GameView.distance1XY[1][0] = GameView.distance2XY[1][0];
GameView.distance1XY[1][1] = GameView.distance2XY[1][1];
return true;
}
return true;
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
return true;
}
return false;
}
#Override
protected void onDraw ( Canvas canvas ) {
canvas.drawColor(Color.GRAY);
GameView.spriteBlocks.onDraw(canvas);
GameView.spriteCharStand.onDraw(canvas);
GameView.spriteKeypadcircle.onDraw(canvas);
}
SpriteBlocks.java
public SpriteBlocks ( GameView gameView, Bitmap bmp ) {
this.bmp = bmp;
SpriteBlocks.width = bmp.getWidth() / SpriteBlocks.BMP_COLUMNS;
SpriteBlocks.height = bmp.getHeight() / SpriteBlocks.BMP_ROWS;
SpriteBlocks.widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
SpriteBlocks.heightPixels = Resources.getSystem().getDisplayMetrics().heightPixels;
SpriteBlocks.centerXScreen = SpriteBlocks.widthPixels / 2;
SpriteBlocks.centerYScreen = SpriteBlocks.heightPixels / 2;
// System.out.println("fififi " + this.weightPixels + "," +
// this.heightPixels);
updateScale();
src2 = new Rect(0, 0, 400, 400);
paintTextPlayCur.setColor(Color.BLACK);
paintTextPlayCur.setTextSize(32);
paintTextSelectBlock.setColor(Color.RED);
paintTextSelectBlock.setTextSize(32);
}
public void updateScale () {
// SpriteBlocks.viewScale = 1;
SpriteBlocks.curBlockWidth = SpriteBlocks.viewScale *
SpriteBlocks.width;
SpriteBlocks.xBlockCount = Math.round(SpriteBlocks.widthPixels /
SpriteBlocks.curBlockWidth);
SpriteBlocks.yBlockCount = Math.round(SpriteBlocks.heightPixels /
SpriteBlocks.curBlockWidth);
SpriteCharStand.curPlayerRenderHeight = SpriteCharStand.playerRenderHeight *
SpriteBlocks.viewScale;
SpriteCharStand.curPlayerRenderWidth = SpriteCharStand.playerRenderWidth *
SpriteBlocks.viewScale;
SpriteCharStand.playerLeftTopX = SpriteBlocks.centerXScreen -
(SpriteCharStand.curPlayerRenderWidth / 2);
SpriteCharStand.playerLeftTopY = SpriteBlocks.centerYScreen -
(SpriteCharStand.curPlayerRenderHeight / 2);
SpriteCharStand.playerRightDownX = SpriteBlocks.centerXScreen +
(SpriteCharStand.curPlayerRenderWidth / 2);
SpriteCharStand.playerRightDownY = SpriteBlocks.centerYScreen +
(SpriteCharStand.curPlayerRenderHeight / 2);
d.pl("viewScale = " +
SpriteBlocks.viewScale +
", width = " +
SpriteBlocks.curBlockWidth);
}
#Override
public void onDraw ( Canvas canvas ) {
update();
if (ClientStatic.minePlayer == null) {
ClientStatic.minePlayer = ClientStatic.playerList
.get(ClientStatic.mineID);
if (ClientStatic.playerList.get(ClientStatic.mineID) == null) {
d.pl(" uuuu " + ClientStatic.mineID);
return;
}
}
// center screen point is this location
minePlayerX = ClientStatic.minePlayer.getLocation().getX();// + 0.5;
minePlayerY = ClientStatic.minePlayer.getLocation().getY();// + 1;
double adderPoint = 0.1;
for ( double adder = 0 ; adder <= 1 ; adder += adderPoint) {
minePlayerX += adderPoint;
// left top of screen is this location
bX = ((minePlayerX) - (SpriteBlocks.xBlockCount / 2) - 1);
bY = ((minePlayerY) + (SpriteBlocks.yBlockCount / 2) + 1);
// right down of screen is this position
cX = ((minePlayerX) + (SpriteBlocks.xBlockCount / 2) + 1);
cY = ((minePlayerY) - (SpriteBlocks.yBlockCount / 2) - 1);
// (SpriteCharStand.curPlayerRenderWidth / 2)
Material me;
Block bbo;
leftXdiff = (minePlayerX * 100) % 100;
leftYdiff = (minePlayerY * 100) % 100;
/*
* leftXdiff = Math.abs(leftXdiff);
* leftYdiff = Math.abs(leftYdiff);
*/
// calculating them from scale
leftXdiff = (curBlockWidth * leftXdiff) / 100;
leftYdiff = (curBlockWidth * leftYdiff) / 100;
// d.pl("cur x " + minePlayerX + " |m " + leftXdiff + " |bx " + bX);
for (double xloop = bX; xloop <= cX; xloop++) { // loop all position X
//for (double yloop = bY; yloop >= cY; yloop--) { // loop all position
// Y
for (double yloop = 140.5 ; yloop == 140.5 ; yloop ++) {
// range Y
if ((yloop < 0) || yloop > (FixVariable.CHUNK_HEIGHT - 1)) {
continue;
}
// get block of that location
bbo = ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(((xloop)), ((yloop)));
me = Material.getMaterial(bbo.getTypeId());
srcX = me.getX(bbo.getData()) * SpriteBlocks.width;
srcY = me.getY(bbo.getData()) * SpriteBlocks.height;
srcKey = ((double) srcX * 10) + ((double) (srcY));
src = srcList.get(srcKey);
if (src == null) {
src = new Rect(srcX, srcY, srcX + SpriteBlocks.width, srcY +
SpriteBlocks.height);
srcList.put(srcKey, src);
}
// position to drawing
if (xloop == 5 && yloop == 140.5) {
d.pl("SPY!! " + tmpXPosition + " = " + xloop + " - " + bX + " ) * 200 -" + leftXdiff);
}
tmpXPosition = ((xloop - bX) * SpriteBlocks.curBlockWidth) -
(leftXdiff );
if (xloop == 5 && yloop == 140.5) {
if (me != Material.BED){
d.pl("bed is spy");
}
if (Math.abs(lastTmpXPosition- tmpXPosition) < 1 &&
(Math.abs(lastTmpXPosition- tmpXPosition) > 0)) {
System.out.println("WT " + (Math.abs(lastTmpXPosition- tmpXPosition)));
}
d.pl("lastTmpXPos = " + lastTmpXPosition + " | " + tmpXPosition);
if (lastTmpXPosition != tmpXPosition) {
lastTmpXPosition = tmpXPosition;
}
}
tmpYPosition = (((SpriteBlocks.yBlockCount) - (yloop - cY + (10*adder) )) * SpriteBlocks.curBlockWidth) +
(leftYdiff);
if (dst == null) {
dst = new Rect();
}
dst.set(
(int) tmpXPosition,
(int) tmpYPosition,
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawBitmap(bmp, src, dst, null);
dst2.set(
(int) (tmpXPosition),
(int) (tmpYPosition),
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawBitmap(GameView.bmpRect, src2, dst2, null);
// break;
}
} // for
bbo = ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(
ClientStatic.minePlayer.getLocation().getX(),
ClientStatic.minePlayer.getLocation().getY());
me = Material.getMaterial(bbo.getTypeId());
srcX = me.getX(bbo.getData()) * SpriteBlocks.width;
srcY = me.getY(bbo.getData()) * SpriteBlocks.height;
srcKey = ((double) srcX * 10) + ((double) (srcY));
tmpXPosition = 5;
tmpYPosition = 5;
dst.set(
(int) tmpXPosition,
(int) tmpYPosition,
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawText(
"playLoc " +
ClientStatic.minePlayer.getLocation().getX() +
"," +
ClientStatic.minePlayer.getLocation().getY(),
200,
200,
paintTextPlayCur);
canvas.drawBitmap(bmp, src, dst, null);
canvas.drawText(
"block " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(
ClientStatic.minePlayer
.getLocation()
.getX(),
ClientStatic.minePlayer
.getLocation()
.getY())
.getTypeId() +
" | chunk " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getChunkAt(
ClientStatic.minePlayer
.getLocation()
.getX())
.getChunkNumberX() +
" | " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getChunkAt(
ClientStatic.minePlayer
.getLocation()
.getX()).getX()
,
200,
300,
paintTextPlayCur);
canvas.drawBitmap(bmp, src, dst, null);
// draw touch block
if (blockTouching != null) {
canvas.drawText("touch " +
blockTouching.getX() +
"," +
blockTouching.getY() +
" = " +
blockTouching.getTypeId() +
":" +
blockTouching.getData()
, 300, 400, paintTextSelectBlock);
}
} // adder
}
Hi I need to make mosaic effect in android.
Convert this:
To this:
How can i do this?
Thank you
/**
* 效果能实现,但是是个耗时的操作
*
* #param bmp
* #param precent 马赛克的程度(0-1)
* 300*300 precent=1 time=57ms
* #return
*/
public static Bitmap getMosaicsBitmap(Bitmap bmp, double precent) {
long start = System.currentTimeMillis();
int bmpW = bmp.getWidth();
int bmpH = bmp.getHeight();
Bitmap resultBmp = Bitmap.createBitmap(bmpW, bmpH, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(resultBmp);
Paint paint = new Paint();
double unit;
if (precent == 0) {
unit = bmpW;
} else {
unit = 1 / precent;
}
double resultBmpW = bmpW / unit;
double resultBmpH = bmpH / unit;
for (int i = 0; i < resultBmpH; i++) {
for (int j = 0; j < resultBmpW; j++) {
int pickPointX = (int) (unit * (j + 0.5));
int pickPointY = (int) (unit * (i + 0.5));
int color;
if (pickPointX >= bmpW || pickPointY >= bmpH) {
color = bmp.getPixel(bmpW / 2, bmpH / 2);
} else {
color = bmp.getPixel(pickPointX, pickPointY);
}
paint.setColor(color);
canvas.drawRect((int) (unit * j), (int) (unit * i), (int) (unit * (j + 1)), (int) (unit * (i + 1)), paint);
}
}
canvas.setBitmap(null);
long end = System.currentTimeMillis();
Log.v(TAG, "DrawTime:" + (end - start));
return resultBmp;
}
/**
* 和上面的函数同样的功能,效率远高于上面
*
* #param bmp
* #param precent
* #return
*/
public static Bitmap getMosaicsBitmaps(Bitmap bmp, double precent) {
long start = System.currentTimeMillis();
int bmpW = bmp.getWidth();
int bmpH = bmp.getHeight();
int[] pixels = new int[bmpH * bmpW];
bmp.getPixels(pixels, 0, bmpW, 0, 0, bmpW, bmpH);
int raw = (int) (bmpW * precent);
int unit;
if (raw == 0) {
unit = bmpW;
} else {
unit = bmpW / raw; //原来的unit*unit像素点合成一个,使用原左上角的值
}
if (unit >= bmpW || unit >= bmpH) {
return getMosaicsBitmap(bmp, precent);
}
for (int i = 0; i < bmpH; ) {
for (int j = 0; j < bmpW; ) {
int leftTopPoint = i * bmpW + j;
for (int k = 0; k < unit; k++) {
for (int m = 0; m < unit; m++) {
int point = (i + k) * bmpW + (j + m);
if (point < pixels.length) {
pixels[point] = pixels[leftTopPoint];
}
}
}
j += unit;
}
i += unit;
}
long end = System.currentTimeMillis();
Log.v(TAG, "DrawTime:" + (end - start));
return Bitmap.createBitmap(pixels, bmpW, bmpH, Bitmap.Config.ARGB_8888);
}
when you want change a bitmap to mosaic bitmap,just invoke function
getMosaicsBitmaps(bmp,0.1)