How to implement CountDownTimer in Recyclerview? - android-studio

Hi I'm working on a small application which sets a countdown. Now I want this countdown to be seen in front of a background inside a recyclerview. So in the end a user will have set multiple countdown timers and these will be displayed with backgrounds inside a recyclerview.
What I have made right now is far from perfect, but it's in the right direction of what I want it to be. The only problem I have right now is, because I'm working with a recyclerview, the view (including the text with the countdown) will be recycled. So if I scroll down, the countdown will be reset. I think that's the problem I'm having but I have no clue how to solve it. This is the most important code:
The activity the recyclerview is in:
package anotherChallenge.example.criminalactivity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.DatePicker;
import com.example.criminalactivity.R;
import java.text.DateFormat;
import java.util.Calendar;
public class Overview extends AppCompatActivity {
private int[] allImages = {
R.drawable.festive1_pictures,
R.drawable.festive2_pictures,
R.drawable.festive3_pictures,
R.drawable.festive4_pictures,
R.drawable.festive5_pictures,
R.drawable.ferrari_materialistic_pictures,
R.drawable.house_materialistic_pictures,
R.drawable.boat_materialistic_pictures,
R.drawable.rolex_materialistic_pictures,
R.drawable.private_jet_materialistic_pictures,
R.drawable.holiday1_pictures,
R.drawable.holiday2_pictures,
R.drawable.holiday3_pictures,
R.drawable.holiday4_pictures,
R.drawable.holiday5_pictures,
R.drawable.meet1_pictures,
R.drawable.meet2_pictures,
R.drawable.meet3_pictures,
R.drawable.meet4_pictures,
R.drawable.meet5_pictures,
R.drawable.other1_pictures,
R.drawable.other2_pictures,
R.drawable.other3_pictures,
R.drawable.other4_pictures,
R.drawable.other5_pictures,
};
private RecyclerView recyclerView2;
private DatePicker datePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overview);
// textClock.setFormat12Hour(null);
// textClock.setFormat24Hour("EEE/MMM d/yyyy hh:mm:ss");
recyclerView2 = findViewById(R.id.recyclerview2);
datePicker = findViewById(R.id.datepicker);
Calendar calendar = Calendar.getInstance();
String currentDate = DateFormat.getDateInstance(DateFormat.FULL).format(calendar.getTime());
System.out.println(currentDate);
// String filledInDate = datePicker.getDayOfMonth() + "/" + datePicker.getMonth() + "/"+
// datePicker.getYear();
adapterForOverview adapter = new adapterForOverview(this, allImages);
recyclerView2.setAdapter(adapter);
recyclerView2.setLayoutManager(new LinearLayoutManager(this));
}
}
Adapter for the recyclerview:
package anotherChallenge.example.criminalactivity;
import android.content.Context;
import android.os.CountDownTimer;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.criminalactivity.R;
public class adapterForOverview extends RecyclerView.Adapter<adapterForOverview.MyViewHolder> {
AddItem addItem;
int[] images;
Context context;
CustomAdapterCardView customAdapterCardView;
public adapterForOverview(Context context, int[] images) {
this.context=context;
this.images=images;
addItem = new AddItem();
// customAdapterCardView = new CustomAdapterCardView(context,
customAdapterCardView.getArrayList());
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
// holder.cardView.setCardBackgroundColor(Color.parseColor("#696969"));
new CountDownTimer(30000,1000) {
#Override
public void onTick(long millisUntilFinished) {
holder.myTextview.setText("The title will be here \n" + millisUntilFinished/1000);
}
#Override
public void onFinish() {
holder.myTextview.setText("Achieved!");
}
}.start();
holder.myImage.setImageResource(images[position]);
// holder.myImage.setImageDrawable(addItem.getDrawable());
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.itemsinoverview,parent,false);
return new MyViewHolder(view);
}
#Override
public int getItemCount() {
return images.length;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
CardView cardView;
ImageView myImage;
TextView myTextview;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.cardview2);
myImage = itemView.findViewById(R.id.imageView);
myTextview = itemView.findViewById(R.id.textviewOfCountdown);
}
}
}
XML Code of the item inside the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<androidx.cardview.widget.CardView
android:id="#+id/cardview2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="4dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintlayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/textviewOfCountdown"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="25sp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

Explanation:
As you know android's recyclerView recycles its views and reuses its viewHolders by calling onBind each time to update the item's data. I noticed that in onBindViewHolder
you create a CountDownTimer every time any data is bound, so you end up with multiple timers updating the same ViewHolder.
Bad solution:
One solution would be to make the adapter's items non-recyclable, but that wouldn't be optimal and negates the recycling ability of the recyclerview.
Good Solution:
The solution is to keep a reference to your timer inside your viewHolder called MyViewHolder. Then in onBindViewHolder check if the timer has already been instantiated. If yes, then cancel the previous timer and afterwards create again a new timer. If not, then there's no need to cancel anything you just proceed to the creation of a new timer object for the first time.
public void onBindViewHolder(#NonNull MyViewHolder holder, final int position) {
if (holder.timer != null) {
holder.timer.cancel();
}
holder.timer = new CountDownTimer(30000, 1000) {
...
}.start();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
...
CountDownTimer timer;
...
}

The problem is that you're creating a new timer every time a new view is bound. You want to keep the data the adapterr is going to display separate from the view that will display it. In this case, you could manage the countdown timer in an object that represents each item in the list. For example (pseudocode):
class MyItem {
val imageResource: Int
val timer: CountDownTimer
}
In the adapter, you hold a list of MyItem and instead of creating a brand new timer, you just set the current value of the existing timer (pseudocode):
public class adapterForOverview extends RecyclerView.Adapter<adapterForOverview.MyViewHolder> {
MyItem[] items;
Context context;
public adapterForOverview(Context context, MyItem[] items) {
this.context=context;
this.items=items;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
timer = items[position].timer
if (timer.isFinished()) {
holder.myTextview.setText("The title will be here \n" + millisUntilFinished/1000);
} else {
holder.myTextview.setText("Achieved!");
}
}
#Override
public int getItemCount() {
return items.length;
}
Finally you would create the timer wherever you're currently initializing the images now. Instead of updating any views, the on tick and finished method just tell the adapter to refresh that specific item in the list, which will then rebind the current timer values (pseudocode):
for (int i = 0; i < allImages.length; i++) {
items[i] = new MyItem()
items[i].image = allImages[i]
items[i].timer = new CountDownTimer(30000,1000) {
#Override
public void onTick(long millisUntilFinished) {
adapter.notifyItemChanged(i)
}
#Override
public void onFinish() {
adapter.notifyItemChanged(i)
}
}.start();
}
Again, this is all pseudo code and won't compiler, but should give you an idea of how to structure your code to solve your problem.

Related

Custom ListView with CustomAdapter Not Showing Up

I am creating fragments inside Android Studio where one of my fragments calls an API and displays the listview with a custom listadapter. However, I have read many similar examples but none can determine why my listview is not appearing.
This is my News Fragment:
package com.example.firebasetestapplication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.firebasetestapplication.databinding.FragmentNewsBinding;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* A simple {#link Fragment} subclass.
* Use the {#link NewsFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class NewsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private Handler mHandler = new Handler(Looper.getMainLooper());
ArrayList<News> newsArrayList = new ArrayList<>();
// FragmentNewsBinding binding;
// Context thiscontext;
public NewsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment NewsFragment.
*/
// TODO: Rename and change types and number of parameters
public static NewsFragment newInstance(String param1, String param2) {
NewsFragment fragment = new NewsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_news,container,false);
TextView textview = v.findViewById(R.id.textview);
ListView listview = v.findViewById(R.id.listview);
// thiscontext = container.getContext();
textview.setText("");
// textView.setText("Trying for the first time");
// Inflate the layout for this fragment
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.jsonbin.io/v3/b/636b51910e6a79321e444107")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String myResponse = response.body().string();
try {
JSONObject jsonObject = new JSONObject(myResponse);
JSONObject record = jsonObject.getJSONObject("record");
JSONArray club_news = record.getJSONArray("Club_News");
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<News>>(){}.getType();
List<News> total_News = gson.fromJson(club_news.toString(),listType);
for(News news : total_News) {
textview.append("Club: " + news.club + " " + news.description + "\n");
newsArrayList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
listview.setAdapter(listAdapter); // line that breaks program
// mHandler.post(new Runnable() {
// #Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
// getActivity().runOnUiThread(new Runnable() {
// #Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
return v;
}
}
The OkHttpRequest successfully gets all the data and organized with Gson. This is my ListAdapter:
package com.example.firebasetestapplication;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class ListAdapter extends ArrayAdapter<News> {
public ListAdapter(#NonNull Context context, ArrayList<News> newsArrayList) {
super(context,R.layout.custom_news_item,newsArrayList);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItemView = convertView;
News news = getItem(position);
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.custom_news_item,parent,false);
}
ImageView club_logo = listItemView.findViewById(R.id.club_logo);
TextView club = listItemView.findViewById(R.id.club);
TextView club_description = listItemView.findViewById(R.id.club_description);
TextView title = listItemView.findViewById(R.id.title);
TextView description = listItemView.findViewById(R.id.description);
TextView time = listItemView.findViewById(R.id.time);
club_logo.setImageResource(R.drawable.frats_color); // Temporary
club.setText(news.getClub());
club_description.setText(news.getClub_description());
title.setText(news.getTitle());
description.setText(news.getDescription());
time.setText(news.getTime());
return listItemView;
}
}
And my News class Model:
package com.example.firebasetestapplication;
public class News {
String club;
String club_description;
String title;
String description;
String time;
public News(String club, String club_description, String title, String description, String time) {
this.club = club;
this.club_description = club_description;
this.title = title;
this.description = description;
this.time = time;
}
public String getClub() {return club;}
public String getClub_description() {return club_description;}
public String getTitle() {return title;}
public String getDescription() {return description;}
public String getTime() {return time;}
public void setClub(String club) {this.club = club;}
public void setClub_description(String club_description) {this.club_description = club_description;}
public void setTitle(String title) {this.title = title;}
public void setDescription(String description) {this.description = description;}
public void setTime(String time) {this.time = time;}
}
Finally, here is my custom_news item xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp">
<LinearLayout
android:id="#+id/first_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="3dp">
<ImageView
android:id="#+id/club_logo"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/frats_color"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:orientation="vertical">
<TextView
android:id="#+id/club"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:textSize="20sp"
android:textColor="#color/black"
android:textStyle="bold"
android:text="Frater Sodalis" />
<TextView
android:id="#+id/club_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Social Club at Abilene Christian University"
android:textStyle="italic"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="15dp"
android:text="8:15pm" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/first_layout"
android:layout_marginTop="0dp"
android:layout_marginStart="10dp"
android:textSize="15sp"
android:textColor="#color/black"
android:textStyle="bold"
android:text="Haunted Forrest is now open! 6869 E North " />
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/title"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:textSize="15sp"
android:text="#string/HF_Example"/>
</RelativeLayout>
</LinearLayout>
and my fragment_news xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".NewsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textStyle="bold"
android:text="News Fragment" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listview"
tools:listitem="#layout/custom_news_item" />
</FrameLayout>
I know if looks like a lot, but I am pretty sure that the error lies around the ListAdapter or the News Fragment. I was looking into whether the getActivity() was passing the correct context for the Fragment or whether my listview.setAdapter(listAdapter); needs a RunOnUiThread somehow in a fragment.
I would very much appreciate it if someone could give me a hint on what's missing for my listview. I know I am pretty close. Thank you so much!
Just in case you are wondering, the Main Activity looks like this:
package com.example.firebasetestapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.firebasetestapplication.databinding.ActivityMainBinding;
import com.firebase.ui.database.FirebaseListAdapter;
import com.firebase.ui.database.FirebaseListOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class MainActivity extends AppCompatActivity {
private TextView greetings;
private Button logout;
//Firebase
FirebaseAuth mAuth = FirebaseAuth.getInstance();
private FirebaseListAdapter<ChatMessage> adapter;
private FirebaseUser user;
private FirebaseUser currentUser;
private DatabaseReference reference;
// Binding
ActivityMainBinding binding;
//Assets
private FloatingActionButton fab;
private String userID;
#SuppressLint("MissingInflatedId")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
replaceFragment(new HomeFragment());
//
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.home:
replaceFragment(new HomeFragment());
case R.id.profile:
break;
case R.id.settings:
break;
case R.id.news:
// startActivity(new Intent(MainActivity.this, NewsActivity.class));
replaceFragment(new NewsFragment());
}
return true;
});
logout = findViewById(R.id.signOut);
// greetings = findViewById(R.id.greeting);
currentUser = mAuth.getCurrentUser();
// fab = findViewById(R.id.fab);
//
// fab.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
// EditText input = findViewById(R.id.input);
// FirebaseDatabase.getInstance()
// .getReference()
// .push()
// .setValue(new ChatMessage(input.getText().toString(),
// FirebaseAuth.getInstance()
// .getCurrentUser()
// .getDisplayName())
// );
//
// // Clear the input
// input.setText("");
// }
// });
logout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(MainActivity.this, LoginActivity.class));
}
});
if (currentUser == null)
{
Intent intent
= new Intent(MainActivity.this,
LoginActivity.class);
startActivity(intent);
}
else
{
// displayChatMessages();
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users");
userID = user.getUid();
reference.child(userID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
User userChat = snapshot.getValue(User.class);
if(userChat != null) {
String fullname = userChat.fullName;
String email = userChat.email;
String age = userChat.age;
// greetings.setText("Welcome, " + fullname + "!");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(MainActivity.this, "Something did not go right!", Toast.LENGTH_SHORT).show();
}
});
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, fragment);
fragmentTransaction.commit();
}
}

Android studio: using SearchView with maps but app keeps crashing and doesn't start

Im trying to use a searchview to create a search bar in a simple map application, however i get the next error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.SearchView.setOnQueryTextListener(android.widget.SearchView$OnQueryTextListener)' on a null object reference
This is my code:
MapsActivity:
package com.example.actividad13mapactivity;
import androidx.fragment.app.FragmentActivity;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.widget.SearchView;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.example.actividad13mapactivity.databinding.ActivityMapsBinding;
import java.io.IOException;
import java.util.List;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private ActivityMapsBinding binding;
SupportMapFragment mapFragment;
SearchView searchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
searchView = findViewById(R.id.sv_location);
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
String location = searchView.getQuery().toString();
List <Address> adressList = null;
if (location != null || !location.equals("")){
Geocoder geocoder = new Geocoder(MapsActivity.this);
try {
adressList = geocoder.getFromLocationName(location,1);
}catch (IOException e){
e.printStackTrace();
}
Address address = adressList.get(0);
LatLng latLng = new LatLng(address.getLatitude(),address.getLongitude());
mMap.addMarker(new MarkerOptions().position(latLng).title(location));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,10));
}
return false;
}
#Override
public boolean onQueryTextChange(String query) {
return false;
}
});
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MapsActivity">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<SearchView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/sv_location"
android:queryHint="Search..."
android:iconifiedByDefault="false"
android:layout_margin="100dp"
android:elevation="5dp"
android:background="#drawable/bg_round"/>
</RelativeLayout>

I am new to Android Studio, and I am creating a wallpaper app, but I want the wallpapers to change automatically after a certain amount of time

this my code it just shows a button and when you press it, it sets the image world as the device wallpaper, if you need more details just ask, I'm new so I don't know what you need to be able to help me :)
package com.example.dailybible;
import androidx.appcompat.app.AppCompatActivity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setWallpaper();
}
} );
}
private void setWallpaper () {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.world);
WallpaperManager manager = WallpaperManager.getInstance(getApplicationContext());
try {
manager.setBitmap(bitmap);
Toast.makeText(this, "Wallpaper set!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
}
}
}
Look at how easy to change an Image on the screen every 5 seconds:
XML file:
setTimeout(function () { alert("JavaScript"); }, 1000);
<LinearLayout 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"
android:orientation="vertical">
<ImageView
android:id="#+id/yourImageViewID"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/image"
android:scaleType="centerCrop"
android:contentDescription="#string/inspect"/>
MainActivity.java file:
I added image1,image2,image3 to "drawable" folder.
public class MainActivity extends AppCompatActivity {
ImageView wallpaper;
public static Integer[] mThumbIds = {
R.drawable.guardian,R.drawable.image1,R.drawable.image2,R.drawable.image3
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wallpaper = findViewById(R.id.yourImageViewID);
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
int i=0;
public void run() {
wallpaper.setImageResource(mThumbIds[i]);
i++;
if(i>mThumbIds.length-1)
{
i=0;
}
handler.postDelayed(this, 5000); //for interval...
}
};
handler.postDelayed(runnable, 2000); //for initial delay..
I see your code has a button.
Here is a simple example of how to change the image with a button.

Recycler View not opening within a Relative Layout. No compilation errors

I have a fragment which is using a Relative layout. Within that XML, I have two views - a TextView and a RecyclerView
There are no compilation errors, but the cards from the RecyclerView don't show up while running the app:
Here's the Fragment code:
package com.hfad.bitsandpizzas;
import android.content.Intent;
import android.os.Bundle;
import android.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class TopFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RelativeLayout layout = (RelativeLayout)inflater.inflate(R.layout.fragment_top, container, false);
RecyclerView pizzaRecycler = (RecyclerView)layout.findViewById(R.id.pizza_recycler);
String[] pizzaNames = new String[2];
for(int i=0; i<2; i++){
pizzaNames[i]=Pizza.pizzas[i].getName();
}
int[] pizzaImages = new int[2];
for(int i=0; i<2; i++){
pizzaImages[i]=Pizza.pizzas[i].getImageResourceId();
}
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(),2);
pizzaRecycler.setLayoutManager(layoutManager);
CaptionedImagesAdapter adapter = new CaptionedImagesAdapter(pizzaNames, pizzaImages);
pizzaRecycler.setAdapter(adapter);
adapter.setListener(new CaptionedImagesAdapter.Listener() {
#Override
public void onClick(int position){
Intent intent = new Intent(getActivity(), PizzaDetailActivity.class);
intent.putExtra(PizzaDetailActivity.EXTRA_PIZZANO, position);
getActivity().startActivity(intent);
}
});
return layout;
}
}
Here is the layout XML:
<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"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/title_top"
android:id="#+id/top_text"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/pizza_recycler"
android:layout_below="#+id/top_text"
android:layout_marginTop="10dp"
android:scrollbars="vertical"/>
And here is the Adapter code:
package com.hfad.bitsandpizzas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class CaptionedImagesAdapter extends RecyclerView.Adapter<CaptionedImagesAdapter.ViewHolder> {
private String[] captions;
private int[] imageIds;
private Listener listener;
public CaptionedImagesAdapter(String[] captions, int[] imageIds){
this.captions = captions;
this.imageIds = imageIds;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardView;
public ViewHolder(CardView v){
super(v);
cardView=v;
}
}
#Override
public CaptionedImagesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CardView cv = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_captioned_image, parent, false);
return new ViewHolder(cv);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
CardView cardView = holder.cardView;
ImageView imageView = (ImageView)cardView.findViewById(R.id.info_image);
Drawable drawable = cardView.getResources().getDrawable(imageIds[position]);
imageView.setImageDrawable(drawable);
imageView.setContentDescription(captions[position]);
TextView textView = (TextView)cardView.findViewById(R.id.info_text);
textView.setText(captions[position]);
cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(listener!=null){
listener.onClick(position);
}
}
});
}
#Override
public int getItemCount() {
return captions.length;
}
public static interface Listener{
public void onClick(int position);
}
public void setListener(Listener listener){
this.listener=listener;
}
}
Thanks!
The TextView's height in your layout is set to "match_parent". The fragment is set to match_parent as well and since probably the activity is set the same way, this means that your TextView will occupy the whole screen.
I imported your code and with minimal changes to by-pass missing objects, I was able to reproduce the problem.
By changing the height for the TextView to be "wrap_content", you'll be making room for the RecyclerView.

Android refreshed UI is overlapping instead of replacing old image when onLayout is called

I've got a fairly simple app I wrote to sharpen my JNI and multi-threading skills which takes either a string of ascii characters to convert to a binary string or a binary character string to convert to an ascii character string. The math behind each conversion is processed via a native lib, and each call to the native code runs on its own thread using AsyncTask so as not to disrupt the UI. The trouble is that whenever onLayout is called when the UI widgets need to change size or position, the new image is placed over top of the still visible old image rather than replacing it. I've tried removing likely culprits (the JNI module, the AsyncTask module) but even when its functionality is stripped and only the UI remains I see the same result of new UI views overlapping instead of replacing older views. As you can see from my code below, I've also variably tried the old setContentView(...) approach to UI hierarchy modeling in addition to the more flexible custom addView model I have active now, but the results were still the same. NOTE: This only happens on device (Nexus 7 running latest 4.2.1 and Nexus S running 4.0.2); in the emulator everything works fine. This would seem to implicate GLES invocations, but I don't make any of my own in this app and obviously this isn't happening to every app on device so it doesn't seem like an OS issue...
Activity Class:
package cresco.ai.asciitobinstring.core;
import android.app.Activity;
import android.os.Bundle;
public class AsciiToBinActivity_Minimalist extends Activity{
private AsciiToBin_Main hMain;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
hMain = new AsciiToBin_Main(this);
hMain.init();
}
#Override
protected void onResume(){
super.onResume();
}
#Override
protected void onPause(){
super.onPause();
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onRestart(){
super.onRestart();
}
#Override
protected void onDestroy(){
super.onDestroy();
}
}
Main manager class:
package cresco.ai.asciitobinstring.core;
import cresco.ai.asciitobinstring.gui.ConversionViewController;
import cresco.ai.asciitobinstring.gui.DefineLayoutParams;
import cresco.ai.asciitobinstring.gui.TutorialViewController;
import cresco.ai.asciitobinstring.math.StringConverter;
import android.app.Activity;
import android.content.res.AssetManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.ViewFlipper;
public class AsciiToBin_Main {
private Activity hAct;
private View mvMainView;
private ViewFlipper mvRootViewFlipper;
private ConversionViewController mvConversionViewController;
private TutorialViewController mvTutorialViewController;
private RelativeLayout mvRootRL;
private AssetManager mvAssetManager;
private LayoutInflater mvInflater;
private StringConverter mvConverter;
public AsciiToBin_Main(Activity act){
hAct = act;
mvConverter = new StringConverter(this);
mvRootRL = new RelativeLayout(hAct);
hAct.addContentView(mvRootRL,
DefineLayoutParams.getParams(DefineLayoutParams.getMM()));
//hAct.setContentView(mvRootRL);
///hAct.setContentView(R.layout.conversion_layout);
}
public void init(){
//Add the viewgroup subclass viewflipper to the rootRL
mvRootViewFlipper = new ViewFlipper(hAct);
mvRootRL.addView(mvRootViewFlipper);
//Instantiate our conversion view controller
mvConversionViewController = new ConversionViewController(this);
mvTutorialViewController = new TutorialViewController(this);
//Fire up the conversion view
mvConversionViewController.initGUI();
mvConversionViewController.initSpinnerElements();
//Fire up the tutorial view
mvTutorialViewController.initGUI();
}
public RelativeLayout getRootRL(){
return mvRootRL;
}
public ViewFlipper getRootViewFlipper(){
return mvRootViewFlipper;
}
public View getMainView(){
return mvMainView;
}
public Activity getAct(){
return hAct;
}
public void setMainView(View v){
mvMainView = v;
}
public void setActivity(Activity a){
hAct = a;
}
public StringConverter getConverter(){
return mvConverter;
}
public void setConverter(StringConverter sc){
mvConverter = sc;
}
}
Conversion View Controller:
package cresco.ai.asciitobinstring.gui;
import cresco.ai.asciitobinstring.core.AsciiToBin_Main;
import cresco.ai.asciitobinstring.core.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
public class ConversionViewController extends View implements OnClickListener,
OnItemSelectedListener{
private AsciiToBin_Main hMain;
private LayoutInflater mvInflater;
private View mvConversionView;
private Button mvConvertB;
private Button mvToTutorialB;
private Spinner mvConversionTypeSP;
private EditText mvAsciiStringET;
private EditText mvBinStringET;
private ArrayAdapter<CharSequence> mvSpinnerAdapter;
public ConversionViewController(AsciiToBin_Main main) {
super(main.getAct());
hMain = main;
}
public void initGUI(){
mvInflater = (LayoutInflater)
hMain.getAct().getSystemService(hMain.getAct().LAYOUT_INFLATER_SERVICE);
mvConversionView = mvInflater.inflate(R.layout.conversion_layout,
hMain.getRootViewFlipper(),false);
hMain.getRootViewFlipper().addView(mvConversionView);
//hMain.getRootRL().addView(mvConversionView);
mvConvertB = (Button)hMain.getAct().findViewById(R.id.convertB);
mvToTutorialB =
(Button)hMain.getAct().findViewById(R.id.conversion_To_Tutorial_B);
mvAsciiStringET =
(EditText)hMain.getAct().findViewById(R.id.asciiStringET);
mvBinStringET = (EditText)hMain.getAct().findViewById(R.id.binStringET);
mvConversionTypeSP =
(Spinner)hMain.getAct().findViewById(R.id.conversionTypeSP);
mvConvertB.setOnClickListener(this);
mvToTutorialB.setOnClickListener(this);
mvConversionTypeSP.setOnItemSelectedListener(this);
}
public void initSpinnerElements(){
mvSpinnerAdapter = ArrayAdapter.createFromResource(hMain.getAct(),
R.array.conversion_choices_array, android.R.layout.simple_spinner_item);
mvSpinnerAdapter.setDropDownViewResource
(android.R.layout.simple_spinner_dropdown_item);
mvConversionTypeSP.setAdapter(mvSpinnerAdapter);
mvConversionTypeSP.setSelection(0);
//Now that that the UI is ready, display it
////hMain.getRootViewFlipper().showNext();
}
#Override
protected void onDraw(Canvas c){
super.onDraw(c);
}
#Override
public void onClick(View v) {
if(v==mvConvertB){
Log.d("me", "button pressed! Conversion type selected currently is
"+mvSpinnerAdapter.getItem(mvConversionTypeSP.getSelectedItemPosition()));
if(mvConversionTypeSP.getSelectedItemPosition() == 0){
//This is the convert ascii to binary string choice
//Calls the native method calculateBinFromAsciiStringJNI
//Not a terribly heavy process, but since it is disparate
//from
//the UI we should probably grant it its own thread...
//Uncomment when UI overlay bug is solved
new
NativeStringConversionTask(0).execute(mvAsciiStringET.getText().toString());
//mvBinStringET.setText(hMain.getConverter().
//calculateBinFromAsciiStringJNI(mvAsciiStringET
//.getText().toString())); //all on the UI thread, not good
}
else if(mvConversionTypeSP.getSelectedItemPosition() == 1){
//This is the convert binary to ascii string choice
//Uncomment when UI overlay bug is solved
new
NativeStringConversionTask(1).execute(mvBinStringET.getText().toString());
//mvAsciiStringET.setText(hMain.getConverter().
//calculateAsciiFromBinStringJNI(mvBinStringET
//.getText().toString())); //all on the UI thread. Not good
}
}
else if(v==mvToTutorialB){
//hMain.getRootViewFlipper().setDisplayedChild(1);
hMain.getRootViewFlipper().showNext();
//hMain.getAct().setContentView(R.layout.tutorial_layout);
}
}
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Log.d("me", "itemselectedlistener received a callback! the position
selected is "+arg2);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
Log.d("me", "itemselectedlistener received a no items slected callaback");
}
//Uncomment once the UI overlay issue is solved
private class NativeStringConversionTask extends AsyncTask<String,Integer,String>{
private int taskID = 0;
public NativeStringConversionTask(int id){
taskID = id;
}
#Override
protected void onPreExecute(){
Log.d("me","in the preExecute of the nativeStringConversion Async
task");
}
#Override
protected String doInBackground(String... s) {
//NB: if we wanted onProgressUpdate to be called with something we
//would
//invoke publishProgress(something) in this function
Log.d("me", "bg task started with taskID "+taskID);
if(taskID == 0){
publishProgress(taskID);
return
hMain.getConverter().calculateBinFromAsciiStringJNI(s[0].toString());
}
else if (taskID == 1){
publishProgress(taskID);
return
hMain.getConverter().calculateAsciiFromBinStringJNI(s[0].toString());
}
else{
publishProgress(taskID);
return "This shouldn't appear. if it does... may the
gods below help us all";
}
}
#Override
protected void onProgressUpdate(Integer... progress){
Log.d("me", "progressUpdate called!");
}
#Override
protected void onPostExecute(String result){
Log.d("me", "calling postExecute...");
if(taskID == 0){
mvBinStringET.setText((String)result);
}
else if (taskID == 1){
mvAsciiStringET.setText((String)result);
}
else{
mvBinStringET.setText("This shouldn't appear. if it
does... may the gods below help us all");
mvAsciiStringET.setText("This shouldn't appear. if it
does... may the gods below help us all");
}
//mvBinStringET.setText(s);
}
}
}
Tutorial View Controller:
package cresco.ai.asciitobinstring.gui;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import cresco.ai.asciitobinstring.core.AsciiToBin_Main;
import cresco.ai.asciitobinstring.core.R;
public class TutorialViewController extends View implements OnClickListener{
private AsciiToBin_Main hMain;
private LayoutInflater mvInflater;
private View mvTutorialView;
private Button mvToConversionB;
public TutorialViewController(AsciiToBin_Main main){
super(main.getAct());
hMain = main;
}
public void initGUI(){
mvInflater = (LayoutInflater)
hMain.getAct().getSystemService(hMain.getAct().LAYOUT_INFLATER_SERVICE);
mvTutorialView = mvInflater.inflate(R.layout.tutorial_layout,
hMain.getRootViewFlipper(),false);
hMain.getRootViewFlipper().addView(mvTutorialView);
mvToConversionB =
(Button)hMain.getAct().findViewById(R.id.tutorial_Conversion_B);
mvToConversionB.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v==mvToConversionB){
//hMain.getRootViewFlipper().setDisplayedChild(0);
hMain.getRootViewFlipper().showNext();
//hMain.getAct().setContentView(R.layout.conversion_layout);
}
}
}
StringConverter:
package cresco.ai.asciitobinstring.math;
import cresco.ai.asciitobinstring.core.AsciiToBin_Main;
public class StringConverter {
private AsciiToBin_Main hMain;
public StringConverter(AsciiToBin_Main main){
hMain = main;
}
//Uncomment once the UI overlay issue is solved
public native String calculateBinFromAsciiStringJNI(String s);
public native String calculateAsciiFromBinStringJNI(String s);
static {
System.loadLibrary("stlport_shared");
System.loadLibrary("ascii2bin");
}
}
conversion_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="#+id/asciiStringET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/conversionTypeSP"
android:layout_centerHorizontal="true"
android:layout_marginTop="71dp"
android:hint="Your ASCII string goes here"
android:text="" />
<EditText
android:id="#+id/binStringET"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/asciiStringET"
android:layout_below="#+id/asciiStringET"
android:layout_marginTop="61dp"
android:hint="Your binary string goes here"
android:text="" />
<Button
android:id="#+id/convertB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/binStringET"
android:text="Convert Strings!" />
<Button
android:id="#+id/conversion_To_Tutorial_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/convertB"
android:text="Read the tutorial on binary numbers" />
<Spinner
android:id="#+id/conversionTypeSP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:layout_marginTop="57dp" />
</RelativeLayout>
tutorial_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="#+id/tutorial_Conversion_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="204dp"
android:text="Return to Conversion" />
</RelativeLayout>
Manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cresco.ai.asciitobinstring.core"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="cresco.ai.asciitobinstring.core.AsciiToBinActivity_Minimalist"
android:label="#string/app_name"
android:theme="#style/FullscreenTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The results I'm seeing are as follows:
Now what's curious is that if I put the app in the background and then re-open it (so onPause and onResume are called) the UI that loads is refreshed properly, with old view artifacts removed. Of course attempting a new string conversion that resizes the edittext widgets creates the overlap again.
Does anyone know what might be behind this? I am targeting sdk revision 17, standard libs with a minSDK of 8. When I first saw this I thought it was a weird side-effect of the new-ish holo UI scheme, so I rolled back the styles.xml to a 2.3 compliant UI scheme but I didn't see any improvement. could be that messed something up separately...
this isn't really a good answer per se because it certainly doesn't explain what happened in the first place, but I found that creating a new project from scratch fixed the odd errors I was seeing; therefore the problem was most likely caused by my mucking about with the UI styles... wish I had a more technical explanation than that, but at present I don't. Anyway, if anyone else runs into this, re-creating your project seems to clear the problem. If anyone has more explanatory details they'd like to add, please feel free!

Resources