In my app I have a custom View
which extends
SurfaceView class. I need to pass it to another thread but after findViewById()
it's still null
. My code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// Widgets
LinearLayout channelCheckboxesLinearLayout;
Spinner channelsSpinner;
Button showButton, removeButton, saveToPdfButton;
ProgressBar progressBar;
TextView progressBarTextView;
SurfaceViewToDraw surfaceViewToDraw;
public static ArrayList<Integer>[] channelsArrayList;
public static boolean asyncTaskFinished = false;
HashSet<Integer> currentlyDisplayedChannels;
Integer selectedChannel;
final String LOG_TAG = "ChannelCheck";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
channelCheckboxesLinearLayout = findViewById(R.id.channels_checkboxes_linear_layout);
channelsSpinner = findViewById(R.id.spinner_channels);
showButton = findViewById(R.id.show_chart);
showButton.setOnClickListener(this);
removeButton = findViewById(R.id.remove_chart);
removeButton.setOnClickListener(this);
saveToPdfButton = findViewById(R.id.savetopdf_button);
saveToPdfButton.setOnClickListener(this);
progressBar = findViewById(R.id.progress_bar);
progressBarTextView = findViewById(R.id.progress_bar_textview);
surfaceViewToDraw = findViewById(R.id.surface_view_to_draw);
currentlyDisplayedChannels = new HashSet<>();
channelsArrayList = new ArrayList[12];
for (int i = 0; i < 12; i++) {
channelsArrayList[i] = new ArrayList<>();
}
readFile();
final Integer[] channelNums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
ArrayAdapter<Integer> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, channelNums);
channelsSpinner.setAdapter(adapter);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.show_chart) {
}
}
private void readFile() {
new ReadFromFileAsyncTask(progressBar, progressBarTextView, showButton, getBaseContext(), surfaceViewToDraw).execute();
if (asyncTaskFinished) {
showButton.setEnabled(true);
}
}
private void permissionRequest() {
if (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (android.os.Build.VERSION.SDK_INT > 23)
requestPermissions(permissions, 0);
}
}
}
activity_main.xml
<FrameLayout 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"
tools:context=".MainActivity"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/channels_checkboxes_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_weight="1">
<TextView
android:text="@string/channels"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:id="@+id/spinner_channels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp">
</Spinner>
<Button
android:id="@+id/show_chart"
android:text="show"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/remove_chart"
android:text="remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<pl.an.pietras.ecgreader.SurfaceViewToDraw
android:id="@+id/surface_view_to_draw"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="23" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_weight="1">
<Button
android:id="@+id/savetopdf_button"
android:text="save to pdf"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/relative_progress_bar"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"/>
<TextView
android:id="@+id/progress_bar_textview"
android:text="Reading file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_above="@+id/progress_bar"
android:textColor="@color/colorAccent"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
</FrameLayout>
SurfaceViewToDraw class
public class SurfaceViewToDraw extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder holder;
int height;
int width;
float mmToPx;
int[] channelsPositions;
Paint minorGridLinesPaint;
Paint majorGridLinesPaint;
Paint descriptionsPaint;
Paint referencePulsePaint;
Paint signalPaint;
int channels = 12;
final int descriptionsXPos = 15;
final int referencePulseXMargin = 5;
final int referencePulseYMargin = 5;
final float distanceBeetweenSamples;
final float mVtopx = 10 / 100 * mmToPx;
final float signalInitPosX = descriptionsXPos + 15;
float signalPosX;
float[] initPathsY;
public SurfaceViewToDraw(Context context, AttributeSet attrs) {
super(context);
holder = getHolder();
holder.addCallback(this);
mmToPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, getResources().getDisplayMetrics());
distanceBeetweenSamples = 25 / 128 * mmToPx;
minorGridLinesPaint = new Paint();
minorGridLinesPaint.setColor(Color.parseColor("#9c9c9c"));
majorGridLinesPaint = new Paint();
majorGridLinesPaint.setColor(Color.parseColor("#595959"));
descriptionsPaint = new Paint();
descriptionsPaint.setColor(Color.BLACK);
descriptionsPaint.setTextSize(20);
descriptionsPaint.setStrokeWidth(2);
referencePulsePaint = new Paint();
referencePulsePaint.setColor(Color.parseColor("#cc0000"));
referencePulsePaint.setStyle(Paint.Style.STROKE);
referencePulsePaint.setStrokeWidth(3);
signalPaint = new Paint();
signalPaint.setColor(Color.BLACK);
signalPaint.setStrokeWidth(3);
signalPaint.setStyle(Paint.Style.STROKE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
height = getHeight();
width = getWidth();
setChannelsPositions(channels);
Canvas canvas = getHolder().lockCanvas();
canvas.drawARGB(255, 255, 179, 102);
drawGridlines(canvas);
drawDescriptions(canvas);
canvas.drawPath(drawReferencePulse(), referencePulsePaint);
getHolder().unlockCanvasAndPost(canvas);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void drawGridlines(Canvas canvas) {
float gridLine = 0;
int i = 0;
// Drawing horizontal lines
while (gridLine < height) {
i++;
gridLine += mmToPx;
if (!(i % 5 == 0)) {
canvas.drawLine(0, gridLine, width, gridLine, minorGridLinesPaint);
} else {
canvas.drawLine(0, gridLine, width, gridLine, majorGridLinesPaint);
}
}
gridLine = 0;
i = 0;
// Drawing vertical lines
while (gridLine < width) {
i++;
gridLine += mmToPx;
if (!(i % 5 == 0)) {
canvas.drawLine(gridLine, 0, gridLine, height, minorGridLinesPaint);
} else {
canvas.drawLine(gridLine, 0, gridLine, height, majorGridLinesPaint);
}
}
}
public void setChannelsPositions(int channels) {
int distanceBeetwenChannels = height / channels;
int initPos = distanceBeetwenChannels / 2;
channelsPositions = new int[channels];
for (int i = 0; i < channels; i++) {
channelsPositions[i] = initPos + i * distanceBeetwenChannels;
}
}
public void doDraw() {
Canvas canvas = getHolder().lockCanvas();
canvas.drawARGB(255, 255, 179, 102);
drawGridlines(canvas);
drawDescriptions(canvas);
canvas.drawPath(drawReferencePulse(), referencePulsePaint);
drawPath(canvas);
getHolder().unlockCanvasAndPost(canvas);
}
public void drawDescriptions(Canvas canvas) {
for (int i = 0; i < channels; i++) {
canvas.drawText(String.valueOf(i), descriptionsXPos, channelsPositions[i], descriptionsPaint);
}
}
public Path drawReferencePulse() {
Path path = new Path();
path.moveTo(referencePulseXMargin, height - referencePulseYMargin);
path.lineTo(referencePulseXMargin + 5, height - referencePulseYMargin);
path.lineTo(referencePulseXMargin +5, height - referencePulseYMargin - mmToPx * 10);
path.lineTo(referencePulseXMargin + mmToPx * 5, height - referencePulseYMargin - mmToPx *10);
path.lineTo(referencePulseXMargin + mmToPx * 5, height -referencePulseYMargin);
path.lineTo(referencePulseXMargin + mmToPx * 5 + 5, height - referencePulseYMargin);
return path;
}
private void drawPath(Canvas canvas) {
signalPosX = signalInitPosX;
Path[] signalPaths = new Path[channels];
for (int i = 0; i < channels; i++) {
signalPaths[i] = new Path();
}
initPathsY(signalPaths, canvas);
drawPaths(signalPaths, canvas);
}
private void initPathsY(Path[] signalPaths, Canvas canvas) {
initPathsY = new float[channels];
for (int i = 0; i < channels; i++) {
initPathsY[i] = channelsPositions[i] - channelsArrayList[i].get(0);
signalPaths[i].moveTo(signalInitPosX, initPathsY[i]);
Log.d("SurfaceViewToDraw", "" + initPathsY[i]);
}
}
private void drawPaths(Path[] signalPaths, Canvas canvas) {
int samples = channelsArrayList[0].size();
for (int i = 1; i < samples; i++) {
signalPosX += distanceBeetweenSamples;
for (int j = 0; j < channels; j++) {
signalPaths[i].lineTo(signalPosX, channelsArrayList[j].get(i));
}
}
for (int i = 0; i < channels; i++) {
canvas.drawPath(signalPaths[i], signalPaint);
}
}
}
After surfaceViewToDraw = findViewById(R.id.surface_view_to_draw);
the surfaceViewToDraw
is still null
and I don't know why. Can someone tell me what's wrong with my code?
Thanks.