everyone! I'm new to Android development and I'm having troubles while trying to set an specific position to the seek bar's thumb.
I want to set the seek bar's progress to it's initial position (in this case 4) when the user releases the thumb, in order to do this, I'm trying to use the method onStopTrackingTouch, but it looks like it's not being called when the user releases the seek bar thumb. There are no errors indicated by Eclipse, the program runs normally, the only problem is that when I release the thumb, it does not return to the initial position.
Detail: I'm using a Vertical Seek Bar, can this be the reason of the problem?
Here's the activity code:
package renatox.play.bluetoothcommander;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.SeekBar;
public class MainActivity extends Activity implements SensorEventListener {
private VerticalSeekBar acelerador;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Sets the Main Activity layout
setContentView(R.layout.activity_main);
// Gets the VerticalSeekBar
acelerador = (VerticalSeekBar) findViewById(R.id.acelerador);
acelerador
.setOnSeekBarChangeListener(new VerticalSeekBar.OnSeekBarChangeListener() {
// I've tried using SeekBar.OnSeekBarChangeListener() and VerticalSeekBar.OnSeekBarChangeListener()
#Override
public void onStopTrackingTouch(SeekBar arg0) {
acelerador.setProgress(4);
Log.i("Acelerador", "O usuário soltou o acelerador");
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
Log.i("Acelerador", "O usuário pegou o acelerador");
}
// Pega os valores do acelerador quando mudam
#Override
public void onProgressChanged(SeekBar arg0, int arg1,
boolean arg2) {
int velocidade = acelerador.getProgress();
Log.i("Acelerador", "Velocidade atual: " + velocidade);
}
});
}
Here's the xml layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/fundo"
android:keepScreenOn="true"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<renatox.play.bluetoothcommander.VerticalSeekBar
android:id="#+id/acelerador"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_marginBottom="30dp"
android:layout_marginRight="5dp"
android:layout_marginTop="30dp"
android:max="8"
android:maxHeight="0dp"
android:minHeight="0dp"
android:progress="4"
android:progressDrawable="#drawable/progress"
android:thumb="#drawable/thumb" />
</RelativeLayout>
And here is the VerticalSeekBar class
package renatox.play.bluetoothcommander;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;
public class VerticalSeekBar extends SeekBar {
protected OnSeekBarChangeListener changeListener;
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setSelected(true);
setPressed(true);
if (changeListener != null)
changeListener.onStartTrackingTouch(this);
break;
case MotionEvent.ACTION_UP:
setSelected(false);
setPressed(false);
if (changeListener != null)
changeListener.onStopTrackingTouch(this);
break;
case MotionEvent.ACTION_MOVE:
int progress = getMax()
- (int) (getMax() * event.getY() / getHeight());
setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
if (changeListener != null)
changeListener.onProgressChanged(this, progress, true);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
Can anyone give me a hint of what might be happening?
Thank you very much!!
Thought I would post this as an official "answer" since it helped me with my code. (answered by Renato Henz)
I've just added this to the "VerticalSeekBar.java": #Override public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) { this.changeListener = mListener; } If you need any further help, please tell me. Good luck with your code!
I found that adding in this code, along with the code previously mentioned, helps with some issues:
#Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
Hello if you change your code like this it will work.
case MotionEvent.ACTION_UP:
super.onTouchEvent(event);
// your code here.
return true;
When I add in aboce setOnSeekBarChangeListner code in the VerticalSeekBar.java, the myControl.setOnseekBarChangeListener code stops working altogether. i.e. OnProgrressChanged stops.
I am trying to enable the code in my activity to the Toast fires (just a placeholder)
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
Toast.makeText(APG.this, "Change OD Done", Toast.LENGTH_SHORT).show();
}
you have to define OnSeekBarChangeListener in VerticalSeekbar then it will work
Try it in VerticalSeekBar like
private OnSeekBarChangeListener onChangeListener;
#Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
this.onChangeListener = onChangeListener;
}
If you have missed out, just call within onTouchEvent.
super.onTouchEvent(event);
Related
It's an old book and has this example of drawing on the screen. So after typing the whole program, it's not behaving as it was said in the books that I'll allow you to draw on the screen.
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;
import android.provider.Settings;
import android.provider.Settings.Panel;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class dragAndDrawActivity extends Activity
{
Paint paint;
Point point1, point2;
Path path;
List<Path> paths=new ArrayList<Path>();
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(new Panel(this));
}
class Panel extends View implements View.OnTouchListener{
public Panel(Context context)
{
super(context);
paint=new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
this.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.drawColor(Color.BLACK);
for (Path path: paths)
{
canvas.drawPath(path,paint);
}
}
#Override
public boolean onTouch(View view,MotionEvent event)
{
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
point1=new Point();
point1.x=(int) event.getX();
point1.y=(int) event.getY();
path.moveTo(point1.x, point1.y);
}
else if(event.getAction()==MotionEvent.ACTION_MOVE)
{
point2 =new Point();
point2.x=(int) event.getX();
point2.y=(int) event.getY();
path.lineTo(point2.x, point2.y);
paths.add(path);
invalidate();
}
return true;
}
}
}
Build gets successful and apk install, but when you try to draw something on the screen, nothing happens.
and the background color also does not apply so there must be some issue with this code.
You should extract it to a custom view and add it to activity layout with alignment constrains. Furthermore, you need to init path variable before using it.
This is how I write it with Kotlin, you can convert back to Java
Panel class
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.Nullable
class Panel : View, View.OnTouchListener {
var paint: Paint? = null
var point1: Point? = null
var point2:Point? = null
var path: Path = Path()
var paths: ArrayList<Path> = ArrayList()
init {
paint = Paint()
paint?.color = Color.GREEN
paint?.strokeWidth = 10f
paint?.style = Paint.Style.STROKE
this.setOnTouchListener(this)
}
constructor(context: Context): super(context)
constructor(context: Context, #Nullable attrs: AttributeSet): super(context, attrs)
override fun onDraw(canvas: Canvas) {
canvas.drawColor(Color.BLACK)
paint?.let {
for (path in paths) {
canvas.drawPath(path, it)
}
}
}
override fun onTouch(view: View, event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
point1 = Point()
point1?.x = event.x.toInt()
point1?.y = event.y.toInt()
path.moveTo((point1?.x?:0)*1f, (point1?.y?:0)*1f)
} else if (event.action == MotionEvent.ACTION_MOVE) {
point2 = Point()
point2?.x = event.x.toInt()
point2?.y = event.y.toInt()
path.lineTo((point2?.x?:0)*1f, (point2?.y?:0)*1f)
path.let {
paths.add(it)
}
invalidate()
}
return true
}
}
activity layout
<androidx.constraintlayout.widget.ConstraintLayout
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<com.martin.screst.customviews.Panel
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Activity class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
Good Evening,
I minimized my large project onto a small scale one which still keeps all the aspects of issue I'm having. I'm using an activity that draws SurfaceView background underneath a single Button. On press that Button adds a new fragment (to an empty FrameLayout that's in MainActivities XML layout) which as well holds SurfaceView and three buttons in ConstraintLayout. Button works as intended and calls the Fragments, but only the static layout part is being drawn(three buttons) as for SurfaceView it only draws Initial Canvas and keeps redrawing same Frame, even tho Thread keeps on calling the Draw method with updated values(in this case Color). ThreadPool is used to create two instances that call update and draw methods for SurfaceView(MaintActivity and Fragment) class objects(this part works as intended).
I'm also getting this line in Log, right about where the issue begins.
D/MY FRAGMENT VIEW: >> INIT
D/MY FRAGMENT VIEW: SURFACE CREATED
D/MY_FRAGMENT: SURFACE CREATED
D/MY FRAGMENT VIEW: SURFACE CHANGED
D/MY_FRAGMENT: SURFACE CHANGED
D/MY FRAGMENT VIEW: DRAW PLANET
D/: HostConnection::get() New Host Connection established 0xb2d1d780, tid 9982
D/MY FRAGMENT VIEW: DRAW PLANET
D/MY FRAGMENT VIEW: DRAW PLANET
D/MY FRAGMENT VIEW: DRAW PLANET
D/MY FRAGMENT VIEW: DRAW PLANET
Code samples bellow:
package com.badcompany.testfragmentview;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private MyActivityView gameView;
private static final String TAG = "MAIN";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
gameView = findViewById(R.id.myview);
SurfaceHolder gholder = gameView.getHolder();
gholder.addCallback(this);
gameView.setLayoutParams(new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT));
Button btn_map = findViewById(R.id.start);
btn_map.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
displayMapFragment();
return true;
}
return false;
}
});
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, ">> SURFACE CREATED");
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, ">> SURFACE CHANGED");
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, ">> SURFACE DESTROYED");
}
private void displayMapFragment() {
MyFragment myFragment = new MyFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.myMapSpace, myFragment).addToBackStack(null)
.commit();
/*fragmentTransaction.add(R.id.fragment_container, simpleFragment).addToBackStack(null).commit();
mButton.setText(R.string.close);
isFragmentDisplayed = true;*/
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.badcompany.testfragmentview.MyActivityView
android:id="#+id/myview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="#+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="#+id/myMapSpace"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
MyActivityView.java
package com.badcompany.testfragmentview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
public class MyActivityView extends ParentGameView implements SurfaceHolder.Callback {
private static final String TAG = "MY ACTIVITY VIEW";
public MyActivityView(Context context) {
super(context);
}
public MyActivityView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
setFocusable(true);
}
public MyActivityView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyActivityView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE CREATED");
MyExecutor.getInstance().execute(new GameRunnable(surfaceHolder, this));
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "SURFACE CHANGED");
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE DESTROYED");
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.YELLOW);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(x, 100, 200, paint);
}
}
MyFragment.java
package com.badcompany.testfragmentview;
import android.os.Bundle;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
public class MyFragment extends Fragment implements SurfaceHolder.Callback {
private static final String TAG = "MY_FRAGMENT";
private MyFragmentView myFragmentView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
//AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final View rootView = inflater.inflate(R.layout.fragment_my, viewGroup, false);
myFragmentView = rootView.findViewById(R.id.myMapView);
SurfaceHolder mSurfaceHolder = myFragmentView.getHolder();
mSurfaceHolder.addCallback(this);
myFragmentView.setLayoutParams(new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT));
Button selectGalaxyMap = rootView.findViewById(R.id.btn_select_galaxy_map);
Button selectSolarSystemMap = rootView.findViewById(R.id.btn_select_solar_map);
Button selectPlanetMap = rootView.findViewById(R.id.btn_select_planet_map);
selectGalaxyMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "SELECTED GALAXY");
myFragmentView.setColor(1);
Toast.makeText(getActivity(), "SELECT GALAXY", Toast.LENGTH_SHORT).show();
}
});
selectSolarSystemMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
myFragmentView.setColor(2);
Log.d(TAG, "SELECTED SYSTEM");
Toast.makeText(getActivity(), "SELECT SYSTEM", Toast.LENGTH_SHORT).show();
}
});
selectPlanetMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "SELECT PLANET", Toast.LENGTH_SHORT).show();
myFragmentView.setColor(3);
Log.d(TAG, "SELECTED PLANET");
}
});
return rootView;
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE CREATED");
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "SURFACE CHANGED");
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE DESTROYED");
}
}
fragment_my.xml
<com.badcompany.testfragmentview.MyFragmentView
android:id="#+id/myMapView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#color/colorPrimary"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<Button
android:id="#+id/btn_select_planet_map"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="#null"
android:text="SELECT PLANET"
android:textStyle="bold" />
<Button
android:id="#+id/btn_select_solar_map"
app:layout_constraintRight_toLeftOf="#id/btn_select_planet_map"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="#null"
android:text="SELET SYSTEM"
android:textStyle="bold" />
<Button
android:id="#+id/btn_select_galaxy_map"
app:layout_constraintRight_toLeftOf="#id/btn_select_solar_map"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="#null"
android:text="SELECT GALAXY"
android:textStyle="bold" />
</android.support.constraint.ConstraintLayout>
package com.badcompany.testfragmentview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
public class MyFragmentView extends ParentGameView implements SurfaceHolder.Callback {
private static final String TAG = "MY FRAGMENT VIEW";
private int Colors;
public MyFragmentView(Context context) {
super(context);
init(context);
}
public MyFragmentView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyFragmentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public MyFragmentView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
getHolder().addCallback(this);
Log.d(TAG, ">> INIT ");
setFocusable(true);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
if(Colors == 2)
drawSolarMap(canvas);
else if(Colors == 1)
drawGalaxyMap(canvas);
else drawPlanetMap(canvas);
}
private void drawGalaxyMap(Canvas canvas){
Log.d(TAG, "DRAW GALAXY");
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawCircle(x, 100, 100, paint);
}
private void drawSolarMap(Canvas canvas){
Log.d(TAG, "DRAW SYSTEM");
canvas.drawColor(Color.RED);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawCircle(x, 100, 100, paint);
}
private void drawPlanetMap(Canvas canvas){
Log.d(TAG, "DRAW PLANET");
canvas.drawColor(Color.GREEN);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawCircle(x, 100, 100, paint);
}
#Override
public void update() {
super.update();
}
public void setColor(int color){
Colors = color;
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE CREATED");
MyExecutor.getInstance().execute(new GameRunnable(surfaceHolder, this));
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "SURFACE CHANGED");
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "SURFACE DESTROYED");
}
}
Extra classes that might not have relevance
GameInterface.java
package com.badcompany.testfragmentview;
/**
* Created by Donatas on 18/12/2018.
*/
import android.graphics.Canvas;
public interface GameInterface {
public void draw(Canvas canvas);
public void update();
}
ParentGameView.java
package com.badcompany.testfragmentview;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceView;
public class ParentGameView extends SurfaceView implements GameInterface{
private static final String TAG = "PARENT_GAME_VIEW";
protected int x = 0;
public ParentGameView(Context context) {
super(context);
}
public ParentGameView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ParentGameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ParentGameView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void update() {
x++;
}
#Override
public void draw(Canvas canvas){
super.draw(canvas);
}
}
MyExecutor.java
package com.badcompany.testfragmentview;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyExecutor {
private static final ExecutorService executor = Executors.newCachedThreadPool();
public static ExecutorService getInstance(){
return executor;
}
public static void ShutDown(){
executor.shutdown();
}
}
GameRunnable.java
package com.badcompany.testfragmentview;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
public class GameRunnable implements Runnable {
private static final String TAG = "GAME_RUNNABLE";
private volatile boolean running = true;
private final int maxFPS = 30;
private double averageFPS;
private Canvas canvas;
private final SurfaceHolder surfaceHolder;
private volatile ParentGameView gameView;
public GameRunnable(SurfaceHolder surfaceHolder, ParentGameView gameView) {
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
#Override
public void run() {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
long startTime;
long timeMillis = 1000/maxFPS;
long waitTime;
int frameCount = 0;
long totalTime = 0;
long targetTime = 1000/maxFPS;
while(running){
startTime = System.nanoTime();
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if(canvas != null){
synchronized (surfaceHolder){
gameView.update();
gameView.draw(canvas);
}
} else {
Log.d(TAG, "Thread finished work");
return;
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
if(canvas != null){
try{
surfaceHolder.unlockCanvasAndPost(canvas);
}catch (Exception e){e.printStackTrace();}
}
}
timeMillis = (System.nanoTime() - startTime)/1000000;
waitTime = targetTime - timeMillis;
try{
if(waitTime>0)
Thread.sleep(waitTime);
} catch (Exception e){e.printStackTrace();}
totalTime += System.nanoTime() - startTime;
frameCount++;
if(frameCount == maxFPS){
averageFPS = 1000/((totalTime/frameCount)/1000000);
frameCount = 0;
totalTime = 0;
//debug System.out.println("AVERAGE FPS: " + avaragFPS);
}
}
}
}
Thanks for looking into this and if you need additional info leave a comment.
Found an awful solution myself, the issue is that MainActivity does not ask for next frame because it deems fragment view to be finished, calling invalidate() method in a Thread makes the activity to keep on asking for updated views.
If you manage to find a better solution please update this post, thanks.
I have an app that displays random characters vertically on the screen (like in the matrix movie) and I would like to add buttons to change the color of these chars when pressed, but I'm unable to call the method setColor of paintTxt variable from MainActivity.
This is my code,
EffetMatrix effetMatrix = new EffetMatrix();//Error in ()
final Paint paintTxt = effetMatrix.paintTxt;
paintTxt.setColor(Color.RED);
But the editor shows an error:
EffetMatrix(Context, AttributSet) in EffetMatrix cannot be applied to ()
the EffetMatrix class code
package com.esqmo.apps.effetmatrix;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.content.Context;
import android.widget.Button;
/**
* Created by esQmo on 04/10/2016.
*/
public class EffetMatrix extends View {
private static final Random ALEATOIRE = new Random();
private int larg, haut;
private Canvas toile;
private Bitmap toileBmp;
private int taillePolice = 40;
private int tailleColonne;
private char[] chars = "01".toCharArray();
private int[] posTxtParColonne;
public Paint peindreTxt, peindreArrPlan, peindreArrPlanBmp, peindreInitArrPlan;
public EffetMatrix(Context context, AttributeSet attrs) {
super(context, attrs);
peindreTxt = new Paint();
peindreTxt.setStyle(Paint.Style.FILL);
peindreTxt.setColor(Color.BLUE);
peindreTxt.setTextSize(taillePolice);
peindreArrPlan = new Paint();
peindreArrPlan.setStyle(Paint.Style.FILL);
peindreArrPlan.setColor(Color.BLACK);
peindreArrPlan.setAlpha(5);
peindreArrPlanBmp = new Paint();
peindreArrPlanBmp.setColor(Color.BLACK);
peindreInitArrPlan = new Paint();
peindreInitArrPlan.setColor(Color.BLACK);
peindreInitArrPlan.setAlpha(255);
peindreInitArrPlan.setStyle(Paint.Style.FILL);
}
#Override
protected void onSizeChanged(int l, int h, int ancl, int anch) {
super.onSizeChanged(l, h, ancl, anch);
larg = l;
haut = h;
toileBmp = Bitmap.createBitmap(larg, haut, Bitmap.Config.ARGB_8888);
toile = new Canvas(toileBmp);
toile.drawRect(0, 0, larg, haut, peindreInitArrPlan);
tailleColonne = larg / taillePolice;
posTxtParColonne = new int[tailleColonne + 1];
for (int x = 0; x < tailleColonne; x++) {
posTxtParColonne[x] = ALEATOIRE.nextInt(larg / 2) + 1;
}
}
private void dessineTexte() {
for (int i = 0; i < posTxtParColonne.length; i++) {
toile.drawText("" + chars[ALEATOIRE.nextInt(chars.length)], i * taillePolice,
posTxtParColonne[i] * taillePolice, peindreTxt);
if (posTxtParColonne[i] * taillePolice > larg && Math.random() > 0.980) {
posTxtParColonne[i] = 0;
}
posTxtParColonne[i]++;
}
}
private void dessineToile() {
toile.drawRect(0, 0, larg, haut, peindreArrPlan);
dessineTexte();
}
#Override
protected void onDraw(Canvas toile) {
super.onDraw(toile);
toile.drawBitmap(toileBmp, 0, 0, peindreArrPlanBmp);
dessineToile();
invalidate();
}
public void setCustomColor(int color){
peindreTxt.setColor(color);
invalidate();
}
}
note: variable peindreText = paintText
The main activity code:
package com.esqmo.apps.effetmatrix;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.effect.Effect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button boutton_vert = (Button) findViewById(R.id.b_v);
final Button boutton_bleu = (Button) findViewById(R.id.b_b);
final Button boutton_rouge = (Button) findViewById(R.id.b_r);
final Button boutton_rose = (Button) findViewById(R.id.b_ro);
boutton_bleu.setOnClickListener(this);
boutton_vert.setOnClickListener(this);
boutton_rouge.setOnClickListener(this);
boutton_rose.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
public void passerVert(View v) {
}
public void passerRouge(View v) {
}
public void passerRose(View v) {
}
public void passerBleu(View v) {
}
}
main.xml
<com.esqmo.apps.effetmatrix.EffetMatrix
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/arrPlan"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#040404"
android:id="#+id/linearLayout">
<Button
android:layout_width="70dp"
android:layout_height="match_parent"
android:text="#string/button_vert"
android:onClick="passerVert"
android:id="#+id/b_v"
android:textAppearance="#android:color/holo_blue_dark" />
<Button
android:layout_width="70dp"
android:layout_height="match_parent"
android:text="#string/button_bleu"
android:onClick="passerBleu"
android:id="#+id/b_b"/>
<Button
android:layout_width="70dp"
android:layout_height="match_parent"
android:text="#string/button_rouge"
android:onClick="passerRouge"
android:id="#+id/b_r" />
<Button
android:layout_width="70dp"
android:layout_height="match_parent"
android:text="#string/button_rouge"
android:onClick="passerRose"
android:id="#+id/b_ro" />
</LinearLayout>
PS: I'm a noob in programming.
Sorry for my english
Don't create a new instance of the custom view again. Instead get a reference to the view using its id.
See the following code,
EffetMatrix effetMatrix = (EffetMatrix) findViewById(R.id.arrPlan);
effetMatrix.setCustomTextColor(Color.RED);
Inside EffetMatrix class create a method named setCustomColor as follows,
class EffetMatrix {
...
public void setCustomTextColor(int color){
// Set the color to the paintTxt object
paintTxt.setColor(color);
// invalidate the view to apply the changes
invalidate();
}
...
}
This is how you implement it in your code,
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
EffetMatrix effetMatrix;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
effetMatrix = (EffetMatrix) findViewById(R.id.arrPlan);
...
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.b_b:
effetMatrix.setCustomTextColor(Color.BLUE);
break;
case R.id.b_r:
effetMatrix.setCustomTextColor(Color.RED);
break;
case R.id.b_ro:
effetMatrix.setCustomTextColor(Color.MAGENTA);
break;
}
}
}
You must invalidate your custom view after changing paint color.
effetMatrix.invalidate();
And if you want to display your custom view in editor you must implement :
public EffetMatrix(Context context) {
this(context, null);
}
public EffetMatrix(Context context, AttributeSet attrs) {
super(context, attrs);
}
If you want to make the buttons do something, then you have to set an onClickListener for each button in your main properly. Here's an example for button_bleu,
Get rid of boutton_bleu.setOnClickListener(this); and replace it with
button_bleu.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
effetMatrix.setCustomColor(Color.BLUE);
}
});
Now just do the same for the other 3 buttons.
I'm looking for a colour picker and stumbled over a pretty good one. The Github page is here. However, when trying to use it the logcat spits out an error.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.education.clearmind.tutoria, PID: 6604
android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:353)
at android.app.Dialog.requestWindowFeature(Dialog.java:1066)
at com.pes.androidmaterialcolorpickerdialog.ColorPicker.onCreate(ColorPicker.java:94)
at android.app.Dialog.dispatchOnCreate(Dialog.java:373)
at android.app.Dialog.show(Dialog.java:274)
at com.education.clearmind.tutoria.WhiteboardActivity.openColorPicker(WhiteboardActivity.java:58)
at com.education.clearmind.tutoria.WhiteboardActivity$1.onClick(WhiteboardActivity.java:49)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Here is the code in the WhiteboardActivity where the colour picker should be implemented :
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import com.education.clearmind.tutoria.ui.views.WhiteboardSurface;
import com.pes.androidmaterialcolorpickerdialog.ColorPicker;
import butterknife.Bind;
import butterknife.ButterKnife;
public class WhiteboardActivity extends Activity {
private Button mChangeBrushColorButton;
private ColorPicker mColorPicker;
private Button mOkColorButton;
private int optionsMenuNumberClicks = 0;
#Bind(R.id.whiteboardRelativeLayout) RelativeLayout mWhiteboardRelativeLayout;
#Bind(R.id.whiteboardSurface) WhiteboardSurface mWhiteboardSurface;
#Bind(R.id.floatingActionBar) ImageButton mFloatingActionBarButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whiteboard);
initializeScreenUI();
onFloatingActionBarClick();
}
public void initializeScreenUI() {
ButterKnife.bind(this);
mColorPicker = new ColorPicker(WhiteboardActivity.this, Color.RED, Color.GREEN, Color.BLUE);
mOkColorButton = (Button) mColorPicker.findViewById(R.id.okColorButton);
}
public void onFloatingActionBarClick() {
mFloatingActionBarButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openColorPicker();
}
});
}
public void openColorPicker() {
mColorPicker.show();
mOkColorButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int selectedColorRGB = mColorPicker.getColor();
mWhiteboardSurface.changeBrushColor(selectedColorRGB);
mColorPicker.dismiss();
}
});
}
}
Here is the code in the WhiteboardSurface View:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.education.clearmind.tutoria.model.Brush;
/**
* Created by tomfinet on 06/03/16.
*/
public class WhiteboardSurface extends View {
private Paint mPaint = new Paint();
private Path mPath = new Path();
private Brush mBrush = new Brush(mPaint, mPath);
// Constructor sets up the paint and inherits the superclasses constructor
public WhiteboardSurface(Context context, AttributeSet attrs) {
super(context, attrs);
// Default brush setup
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10f);
}
#Override
protected void onDraw(Canvas canvas) {
// draws the path with the selected paint
canvas.drawPath(mBrush.getPath(), mBrush.getPaint());
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
/**
* gets the xPos and yPos of the touch on the screen and saves them in variables so
* that they can be manipulated into drawing lines and so on.
*/
float xPos = motionEvent.getX();
float yPos = motionEvent.getY();
//TODO: Add the functionality to open options menu on touch event
switch(motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(xPos, yPos);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(xPos, yPos);
break;
default:
return false;
}
invalidate();
return true;
}
public void changeBrushColor(int colorRGB) {
mPaint.setColor(colorRGB);
}
}
Can someone please tell me what I am doing wrong and how to fix it.
If you need anything else, please just ask.
Cheers.
I've searched everywhere, and nothing found!
I need to set the position of my progressDialog in the center horizontal and vertical.
But when i compile my code by command line (i dont use eclipse) an error message is shown:
"cannot find symbol > Gravity..".
I think its a problem in the inclusion, i've imported looot of useless file 'cause i dont know what to import.
Somebody could help me?
Here is the code:
package com.worfut.project;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.content.Context;
import android.content.ContextWrapper;
import android.view.ContextThemeWrapper;
import android.widget.ShareActionProvider;
import android.widget.LinearLayout;
import android.view.Window;
public class MainActivity extends Activity {
WebView WorfutWeb;
ProgressDialog progressBar;
private int progressBarStatus = 0;
private Handler progressBarHandler = new Handler();
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main);
final Activity activity = this;
WorfutWeb = (WebView) findViewById(R.id.mainWebView);
WorfutWeb.getSettings().setSupportZoom(false);
WorfutWeb.getSettings().setBuiltInZoomControls(false);
WorfutWeb.setBackgroundColor(Color.BLACK);
WorfutWeb.setWebViewClient(new myWebClient());
WorfutWeb.getSettings().setJavaScriptEnabled(true);
// prepare for a progress bar dialog
progressBar = new ProgressDialog(this, R.id.mainWebView);
progressBar.setCancelable(true);
progressBar.setIndeterminate(false);
progressBar.getWindow().setGravity(Gravity.CENTER);
progressBar.setMessage("Caricamento in corso..");
progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.show();
WorfutWeb.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, final int progress)
{
activity.setProgress(progress * 100);
progressBar.setProgress(progress);
if(progress == 100)
{
progressBar.dismiss();
}
}
});
WorfutWeb.setWebViewClient(new WebViewClient() {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
{
String html1 = "<html><body><br>";
String html2 = "<div style='background: #007ac1; border: 2px solid lightblue; border-radius: 8px; padding: 4px;'>";
String html3 = "<p style='font-weight: bolder;color: white;'><h2><u>Si è verificato un errore!</u></h3><br>";
String html4 = "Possibili cause:<br><ul><li>";
String html5 = "Non si dispone di una connessione Internet;</li><ul><li>Chiudere l'applicazione</li><li>Attivare la connessione Internet</li><li>Riavviare l'applicazione</li></ul><li>L'applicazione non risponde<ul><li>Chiudere e riaprire l'applicazione</li><li>Scriveteci sul Market Android</li></ul>";
String html6 = "</li></ul></p><br><p align=right><font color=white><em>Worfut Staff.</em> </font></p></div></body></html>";
String mime = "text/html";
String encoding = "utf-8";
view.loadData(html1+html2+html3+html4+html5+html6, mime, encoding);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
});
Animation fadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fadein);
WorfutWeb.startAnimation(fadeInAnimation);
WorfutWeb.loadUrl("http://www.americantrip.altervista.org/try");
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_about:
WorfutWeb.loadUrl("http://americantrip.altervista.org/try/info.php");
// inside the menu button you don't need to call Super.loadUrl, LoadUrl its enough
return true;
case R.id.menu_help:
WorfutWeb.loadUrl("http://americantrip.altervista.org/try/help.php");
// inside the menu button you don't need to call Super.loadUrl, LoadUrl its enough
return true;
case R.id.menu_search:
WorfutWeb.loadUrl("http://americantrip.altervista.org/try/cerca.php");
return true;
case R.id.menu_exit:
finish();
default:
return super.onOptionsItemSelected(item);
}
}
public void onResume() {
super.onResume();
if (WorfutWeb != null) {
WorfutWeb.resumeTimers();
}
}
public void onPause() {
super.onPause();
if (WorfutWeb != null) {
WorfutWeb.pauseTimers();
}
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.dismiss();
}
}
// To handle "Back" kewy press event for WebView to go back to previous screen.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && WorfutWeb.canGoBack()) {
WorfutWeb.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
This is the layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/sfondo"
android:gravity="center">
>
<WebView android:id="#+id/mainWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</LinearLayout>
The part with the error is this:
progressBar.getWindow().setGravity(Gravity.CENTER);
and i think its correct, but maybe i have to import something else.
Thanks yall.
P.S. i've already seen http://developer.android.com/reference/android/widget/LinearLayout.html#setGravity(int)
and i've took from there the "import android.widget.LinearLayout". seems to be the same, dont run.
Try:
import android.view.Gravity;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/sfondo"
>
>
<WebView android:id="#+id/mainWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
modified your layout, i guess the progress wont be at the center as you declared your layout on the center. anyway if that doesn't help you.
the easiest way to do it is.
FrameLayout.LayoutParams para=new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT );
para.gravity = Gravity.CENTER;
progressBar.setLayoutParams(para);
and it should work. if that fixed your issue please do accept the answer so others can get use of it. cheers