Android screen white components getting black on resume - android

I am facing EXTREMELY PECULIAR problem with my android application. I see not a single similar solution anywhere, either on google or on SO.
Here is my screenshot of the app:
This is normal expected output. But when I exit the app and resume again from launcher, often(say 2 out of 5 times) I happen to get the white components(list view and EditText) like this:
In this image, I have touched the first element of listview while taking screenshot so that its shown that the listview items are having actual content and not empty.
Here is my layout resource file main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll"
android:cacheColorHint="#00000000"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:weightSum="15" android:background="#android:color/white">
<EditText
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/edittext" android:layout_weight="2" android:background="#ffffff"
android:textColor="#android:color/black" android:gravity="center" android:hint="Enter Your Text Here"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp" android:layout_weight="2"
android:weightSum="12" android:gravity="center">
<Button android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Tweet"
android:id="#+id/tweetbtn"
android:background="#drawable/mybutton"
android:layout_weight="6"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Search"
android:background="#drawable/mybutton"
android:id="#+id/searchbtn"
android:layout_weight="6"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Most Frequently Tweeted"
android:id="#+id/listviewlabel" android:layout_weight="1" android:gravity="center" android:background="#adadad"
android:textColor="#android:color/black"/>
<ListView
android:cacheColorHint="#00000000"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/listView" android:layout_gravity="center_horizontal" android:layout_weight="10"
android:choiceMode="singleChoice"/>
</LinearLayout>
Please someone help me out with this. Atleast help me resolve the white EditText issue first. That will give me alteast a clue to solve the listview issue.
EDIT:
The listview is dynamically populated by elements. Here is my onStart() method:
#Override
public void onStart(){
super.onStart();
handleFrequentMenuSelected();
}
Here is the handleFrequentMenuSelected():
private void handleFrequentMenuSelected() {
if(!isAccountAdded()){
showToast("Add an account first to get started! Goto Menu and select account.");
}else{
List<StatusElement>aList=getStatusElementsFromSQLiteDatabase();
HashMap<String,Integer> hMap=new HashMap<String, Integer>();
for(StatusElement s:aList){
String tokens[]=s.toString().split(" ");
String outText="";
if(tokens.length>1){
if(tokens[0].contains("/")){
String tokens2[]=tokens[0].split("/");
try{
long l=Long.parseLong(tokens2[0]);
for(int i=1;i<tokens.length;i++){
outText=outText+tokens[i]+" ";
}
}catch(Exception e){
outText=s.toString();
}
}else{
try{
long l=Long.parseLong(tokens[0]);
for(int i=1;i<tokens.length;i++){
outText=outText+tokens[i]+" ";
}
}catch(Exception e){
outText=s.toString();
}
}
}else{
outText=s.toString();
}
outText=outText.trim();
if(hMap.containsKey(outText)){
int cnt=hMap.get(outText);
cnt++;
hMap.put(outText,cnt);
}else{
hMap.put(outText,1);
}
}
hMap= (HashMap<String, Integer>) StaticConstants.sortByValue(hMap);
ArrayList<String>tweets=new ArrayList<String>();
ArrayList<Integer>frequencies=new ArrayList<Integer>();
ArrayAdapter<String>adapter;
int count=0;
for(String s:hMap.keySet()){
tweets.add(s);
frequencies.add(hMap.get(s));
count++;
if(count==50)
break;
}
adapter=new MyCustomFrequentArrayAdapter(this,tweets,frequencies);
listView.setAdapter(adapter);
listViewLabel.setText("Most Frequent Tweets");
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
final String item = (String) parent.getItemAtPosition(position);
editText.setText(System.currentTimeMillis()+" "+item);
}
});
}
}
Here is my MyCustomFrequentArrayAdapter:
class MyCustomFrequentArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final ArrayList<String> values;
private final ArrayList<Integer>frequencies;
public MyCustomFrequentArrayAdapter(Context context, ArrayList<String> values,ArrayList<Integer>frequencies) {
super(context, R.layout.customlistview, values);
this.context = context;
this.values = values;
this.frequencies=frequencies;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.customlistview, parent, false);
TextView textView1 = (TextView) rowView.findViewById(R.id.firstLine);
TextView textView2 = (TextView) rowView.findViewById(R.id.secondLine);
Log.d("Position",""+position);
//Extracting first six words
String s=values.get(position);
String tokens[]=s.split(" ");
String dispText="";
if(tokens.length>6){
for(int i=0;i<6;i++){
dispText=dispText+tokens[i]+" ";
}
}else{
dispText=s;
}
textView2.setText(dispText);
textView1.setText("Frequency:"+frequencies.get(position));
return rowView;
}
}

Referencing a blog post by Romain Guy - Why Is My List Black
ListView has top and bottom fading edges to indicate it is scrollable.
Creating the fading edge has performance issues so ListView has an optimization to improve performance. Unfortunately the optimization causes problems if the background of the ListView is set to something other than the default.
The optimization can be disabled by setting android:cacheColorHint="#00000000" as you are doing BUT quoting from the blog post...
To fix this issue, all you have to do is either disable the cache color hint optimization, if you use a non-solid color background, or set the hint to the appropriate solid color value.
In other words using android:cacheColorHint="#00000000" should only be used for a "non-solid color" (one which is transparent / translucent).
In your case you are using #ffffff which is an RGB value and by default that means its 'A' component (the alpha) will be ff making it fully opaque, i.e., "solid".
So referring to the last part of the above quote...
...set the hint to the appropriate solid color value.
This suggests you should use android:cacheColorHint="#ffffff" to fix the ListView problem.

Related

Android - OnItemClickListener only *sometimes* not working

I have a ListView in one of my activities that I have bound to an ArrayList using a custom ArrayAdapter. I have set an OnItemClickListener to the ListView which should call a method that starts another activity. However, I find that when I click on the ListView items, it only sometimes works. Sometimes it will start the activity as it should; other times it seems to detect the click (the ripple effect appears on the list item) but does nothing; other times it doesn't even appear to detect the click (the ripple effect doesn't appear).
I've tried all the usual suggestions that I've come across: blocking descendants on the parent view item, setting clickable and focusable to false on all the components of the item views, setting isEnabled to return true in the custom adapter, etc, but the behavior remains the same. Any help appreciated. Here is the relevant code:
Activity containing the ListView:
public class ViewCollectionActivity extends AppCompatActivity {
private final String className = this.getClass().getSimpleName();
private CollectionHandler collectionHandler;
private Context context;
private ArrayList<Game> displayedCollection;
private GameCollectionAdapter collectionAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_collection);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
context = this;
collectionHandler = CollectionHandler.getInstance(this);
TextView view = null;
if (collectionHandler.getDisplayedCollection().size() > 0) {
view = (TextView) findViewById(R.id.no_items_textview);
view.setVisibility(View.GONE);
}
String currentDate = collectionHandler.getDateLastSynchronised();
view = (TextView) findViewById(R.id.last_updated_textview);
view.setText("Last synchronised: " + currentDate + " Total games: " + String.valueOf(collectionHandler.getDisplayedCollection().size()));
collectionAdapter = collectionHandler.getCollectionAdapter();
ListView listView = (ListView) findViewById(R.id.collection_list_view);
listView.setAdapter(collectionAdapter);
AdapterView.OnItemClickListener collectionItemClickListener = new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
launchGameDetailsActivity(position);
}
};
listView.setOnItemClickListener(collectionItemClickListener);
}
public void launchGameDetailsActivity(int position){
Log.d(className,"Starting lauchGameDetailsActivity method");
collectionHandler.setSelectedGame(position);
Intent intent = new Intent(this,ViewGameDetailsActivity.class);
startActivity(intent);
Log.d(className, "Ending lauchGameDetailsActivity method");
}
The XML for the activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
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="com.bleachedlizard.ludome.viewcollection.ViewCollectionActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Synchronise Collection"
android:onClick="synchroniseCollection"/>
<TextView
android:id="#+id/last_updated_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Last synchronised: "
android:textAlignment="center"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Display Collection"
android:visibility="gone"
android:onClick="displayCollection"/>
<ListView
android:id="#+id/collection_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#+id/no_items_textview"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="You have no items in your collection."
android:textAlignment="center"
android:textSize="20sp"/>
</LinearLayout>
The XML for the item views:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/collection_item_layout"
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"
android:clickable="false"
android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/collection_item_image"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/testimage"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
/>
<TextView
android:id="#+id/collection_item_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="16dp"
android:singleLine="false"
android:textColor="#android:color/darker_gray"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
<TextView
android:id="#+id/collection_item_plays"
android:layout_width="100dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="8dp"
android:textColor="#android:color/darker_gray"
android:text="Plays: 0"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
</LinearLayout>
The code for the custom adapter:
public class GameCollectionAdapter extends ArrayAdapter<Game> {
private ArrayList<Game> collection;
public GameCollectionAdapter(Context context, int resource, ArrayList<Game> collection){
super(context, resource, collection);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout gameView = (LinearLayout) convertView;
LayoutInflater mInflater = LayoutInflater.from(getContext());
if (gameView == null) {
gameView = (LinearLayout) mInflater.inflate(R.layout.collection_item_view, null);
}
//Game game = collection.get(position);
Game game = super.getItem(position);
if (game != null) {
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView gameTitle = (TextView) gameView.findViewById(R.id.collection_item_name);
TextView numOfPlays = (TextView) gameView.findViewById(R.id.collection_item_plays);
ImageView thumbnail = (ImageView) gameView.findViewById(R.id.collection_item_image);
// check to see if each individual textview is null.
// if not, assign some text!
if (gameTitle != null){
gameTitle.setText(game.getTitle());
}
if (numOfPlays != null){
numOfPlays.setText("Plays: " + String.valueOf(game.getNumOfPlays()));
}
if (thumbnail != null){
thumbnail.setImageBitmap(game.getThumbnail());
}
}
// the view must be returned to our activity
return gameView;
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
I discovered what was causing the problem: the way I had set up the array that backed the ListView meant that it was downloading and storing the Bitmaps for every element in the array all the time. Once I changed the implementation so that it only downloaded the images as the ListView required them, then that seemed to improve performance and the onClickListener started to work fine.
The implementation I used was the exact same one shown here:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I think the issue is due to the position of the item selection whenever you click you have an list position which is passed to your method launchGameDetailActivity(int position) check with log or toast on item click what all the position you are getting do the needful.
Here is my code try this like this if it helps.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(RecipeClass.this, "Position is" + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RecipeClass.this, RecipeIngredients.class)
intent.putExtra("position", position);
startActivity(intent);
}
Check your arraylist value also whether they are not null.

Can the main activity be able to grab elements from two XML files?

UPDATE WITH CODE (Sorry for crappy formatting of my code, some reason it had problems allowing me to post it so I had to mess with the lines for a whole to get it to allow me to save thisedit)
Here is the idea. I have an app that works with Clarifia's image recognition. I generated the app using Google's pre built navegation bar, so there is extra xml files and code for that, but it can be ignored the two needed for this is activity_main.xml and content_main.xml. anyways in content_main.xml it is a linear layout that has an imageview and a listview. My goal is to dynamically generate the listview with a list of BUTTONS. each button will have setText() done to it to give it a tag, so for example if a image selected is a dog, and the tags are dog, animal, etc, then that many buttons will be generated, with a setText() of one button being dog, the other button being animal, etc . now Since I have to do a network call, the network call is done in asynctask. After it is done, the method onPostExecute() is called and from there I get the tags. NOW since i got the tags, I want to call set an adapter that will hold an array of buttons, and loop geting the ID for each button and doing settext() on each button with the tags. from there i want to set the adapter to the list view..
Problems:
way to many to count, but I THINK i narrowed it down to me not knowing how to get the "views" from the second xml file to have the elements be used on the first xml file, because everything comes out NULL. I tried googling it but i just keep running into road blocks. I just want to name each button with a tag and put them into listview, but like i said, since these elements are in a different xml file than main_activity, I think this is the problem. so here is the code per request.
MainActivity.java
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener
{
private static final String CLASS = MainActivity.class.getSimpleName();
private Button selectButton;
private Toolbar toolbar;
private NavigationView navigationView;
private Clari
faiData cdata = null;
private ImageView imageview;
private ListView listview;
private TagAdapter adapter;
private List<Button> data;
protected Context context;
private GoogleApiClient client;
protected LinearLayout main;
#Override
protected void onCreate(Bundle savedInstanceState)
{
// THIS IS MY ATTEMPT TO DO THIS
// http://www.java2s.com/Code/Android/UI/UsingtwolayoutxmlfileforoneActivity.htm
super.onCreate(savedInstanceState);
context = MainActivity.this;
main = new LinearLayout (this);
setContentView(R.layout.activity_main);
// AUTO GENERATED stuff left out for nav bar, just showing this line*********
selectButton = (Button) findViewById(R.id.select_button);
selectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent media_intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// START API OVER NET
startActivityForResult(media_intent, cdata.getOKCode());
}
});
// MY STUFF********************************************************
cdata = new ClarifaiData(this);
imageview = (ImageView) findViewById(R.id.image_view);
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == cdata.getOKCode() && resultCode == RESULT_OK)
{
Uri image = intent.getData();
if (image != null) {
// LEFT OUT STUFF FOR IMAGE RESIZING***************************
//************************************************** START LOOKING HERE***************************************
new AsyncTask<Uri, Void, RecognitionResult>()
{
#Override
protected RecognitionResult doInBackground(Uri... image)
{
// SO API CALL OVER INTERNET, SO NEEDED ASYNC
return cdata.recognizeBitmap(image[0]);
}
#Override
protected void onPostExecute(RecognitionResult result)
{
super.onPostExecute(result);
if (cdata.getTags(result))
{
selectButton.setEnabled(true);
selectButton.setText("Select a photo");
// MY ATTEMPT TO GET THE
// http://www.java2s.com/Code/Android/UI/UsingtwolayoutxmlfileforoneActivity.htm
LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout taglayout = (LinearLayout) inflate.inflate(R.layout.tag_list_item_trio_item, null);
LinearLayout.LayoutParams parm = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
listview = (ListView) main.findViewById(R.id.tagview);
main.addView(taglayout, parm);
// this is a arraylist of tags that hold strings
List tags = cdata.getMapTags();
// data is a array of buttons, each button will be labled by each value in tags
data = new ArrayList<Button>();
for (int i = 0; i < tags.size(); i++)
{
// GET ID FOR EACH BUTTON AND PUT IT INTO ARRAY THEN SETTEXT
String loc = "button_item_" + i;
int ID = getResources().getIdentifier(loc, "id", getPackageName());
Button temp = (Button) main.findViewById(R.id.button_item_0);
temp.setText("TEST " + i);
}
// HERE IS THE PROBLEM, I NEED A WAY TO GET THE LAYOUT STUFF FROM MAIN ACTIVITY
adapter = new TagAdapter(MainActivity.this, getResources().getIdentifier("tag_list_item_trio_item", "id", getPackageName()), data);
listview.setAdapter(adapter);
}
else
bottomToast(cdata.getRecError());
}
}.execute(image);
} else {
bottomToast(cdata.getLoadError());
}
}
}
tagAdapter.java
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class TagAdapter extends ArrayAdapter<Button> {
private Context context;
private List<Button> taglist;
public TagAdapter(Context context, int resource, List<Button> objects) {
super(context, resource, objects);
Log.i("Test", "constructor " );
this.context = context;
this.taglist = objects;
}
#Override
public int getCount()
{
return taglist.size();
}
getView(int, android.view.View, android.view.ViewGroup)
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.tag_list_item_dual_item, parent, false);
final Button tag = taglist.get(position);
View view = null;
view = layoutInflater.inflate(R.layout.tag_list_item_trio_item, parent, false);
else
{
view = layoutInflater.inflate(R.layout.tag_list_item_dual_item, parent, false);
Button nameTextView = (Button) view.findViewById(R.id.first_button_dual_item);
nameTextView.setText("test");
Button nameTextView2 = (Button) view.findViewById(R.id.second_button_dual_item);
nameTextView2.setText("test2");
}
return view;
}
}
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:gravity="center|bottom"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:id="#+id/image_view"
android:background="#653fff"
android:layout_weight="0.5"
android:padding="1dp" />
<ListView
android:id="#+id/tagview"
android:layout_width="match_parent"
android:layout_weight="0.35"
android:layout_height="0dp"
android:padding="5dp"
android:background="#68343f"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:textAlignment="center" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:layout_gravity="center_horizontal"
android:textAlignment="center"
/>
<Button
android:id="#+id/select_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sel_image"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:background="#3d88ec" />
</LinearLayout>
tag_list_item_trio.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_centerHorizontal="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAlignment="center"
android:layout_centerInParent="true"
android:orientation="horizontal">
<Button
android:id="#+id/button_item_0"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 1"
android:textColor="#ffffff"
/>
<Button
android:id="#+id/button_item_1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 2"
android:textColor="#ffffff"
/>
<Button
android:id="#+id/button_item_2"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 3"
android:textColor="#ffffff"
/>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_centerHorizontal="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAlignment="center"
android:layout_centerInParent="true"
android:orientation="horizontal">
<Button
android:id="#+id/button_item_0"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 1"
android:textColor="#ffffff"
/>
<Button
android:id="#+id/button_item_1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 2"
android:textColor="#ffffff"
/>
<Button
android:id="#+id/button_item_2"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#000000"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:text="TEST 3"
android:textColor="#ffffff"
/>
</LinearLayout>
One thing you should know is a Listview and its items are virtualized or recycled/reused or duplicated if i should say. so from how i see it i think your approach is off.
This is how i suggest you rectify it, before i get to that i want to clarify the way i understood a portion of your requirement
My goal is to dynamically generate the listview with a list of BUTTONS. each button will have setText() done to it to give it a tag, so for example if a image selected is a dog, and the tags are dog, animal, etc, then that many buttons will be generated, with a setText() of one button being dog
so you are saying you want a listView with 4 buttons on each row.
Do this, _i am taking relevant portions.
private ListView listview; //your listview
private TagAdapter adapter; // your adapter
//we are in oncreate
//i have no knowledge on cdata so bare with me here
//now remove List<Button> data; from your code
we have jumped to the TagAdapter class
private Context context;
//private List<Button> taglist; remove this also
private ArrayList<TheClassThatContainsTags> myTags;//i am assuming this will be cdata or?
//but this list should contain what setText() for a button will get its text
public TagAdapter(Context context) { //this is how your constructor will look
super(context);
Log.i("Test", "constructor " );
this.context = context;
//here you start your async task and put your async task logic here
//if the async task requires some objects or items which is not in this class
// since this is a separate class, you can inject them, when i say inject
// put them in the constructor of TagAdapter like you inject the Context
//object instance, so it might change to
// public TagAdapter(Context context,OneMoreClassIfIWant omciiw) {
// here you aysnc task will execute, now when onPostExecute is triggered/
//called you will do the following, but so remove all the code lines
// you currently have under onPostExecute
// onPostExecute has triggered
myTags = // the tag items result from onpostExecute
//now your myTags Arraylist of type TheClassThatContainsTags has been
//instantiated
}
we are now moving to getCount still in your custom adapter
#Override
public int getCount() {
return (myTags == null) ? 0 : myTags.size();
}
we are now moving to getView still in your custom adapter
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
//in your posted getview, did you edit that too? if not does it give you errors?
//nevermind
// what you do here is check if convertView is null and instantiate it
// the position here in your method parameter is the index in your myTags
// list
if(convertView == null){
//guess you know how to do this. it should be the same as your old
//getview minus this final Button tag = taglist.get(position);
// and the line below it.
}
//here we are still in the getview - what you do is ,
you find what particular button you want by convertView.findViewById()
//my understanding as i pointer out is you want to have 4 buttons in a row
//it should be something like this
Button b = convertView.findViewById(R.id.button1);
b.setText(getItem(position));//getItem() is an instance method for the
//class you are extending, and it returns an Object of Type T, which in my
//example is TheClassThatContainsTags.class;
// and you can do the same for the next 3 buttons
}
we are out of your getview and custom adapter class , and we are in your oncreate .
here set when you need your tags then you do
tagAdapter = new TagAdapter(context,anyIfDesired_OtherInjections);
listview.setAdatper(tagAdapter);
now you are done. Hope it helps, also please read listview and Arraylist Adapter so you get a foresight of what you are doing and what i have posted here. it will help you trim down the hours you waste, if you spend 12 hours on the docs your will spend 5 minutes writing this and the next time you want to replicate it will be the same 5 minutes.
Be good sir and wish you success.

Changing width of individual items in a listview

So I've searched around for an answer or a possible solution to this problem for a couple weeks now and still haven't gotten any farther. I'm working on building an app that rewards users with points after certain things. One of the pages they can visit is a leader board based off of the friends the user has.
I'm able to implement the leader board and print the users in order based off of their points, but can't implement a bar graph style look. Like So: http://imgur.com/tF51RsA
(Had to post a link because I can't paste a picture in here)
Here is what I've tried so far:
1. Adding a to xml and trying to getLayoutParams in the custom adapter then set the width, which didn't work.
2. using onDraw to draw a rectangle over top of the list item.
Here is my Leader board xml file (or close to it):
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/leader_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left|top"
android:background="#00000000">
</LinearLayout>
My listview row xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/user_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:background="#drawable/ic_default_user"/>
<TextView
android:id="#+id/rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="10dp"
android:layout_toRightOf="#+id/user_image"/>
<TextView
android:id="#+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="20dp"
android:textSize="16sp"
android:layout_toRightOf="#+id/rank"/>
<TextView
android:id="#+id/score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/user_name"
android:gravity="right"
android:paddingRight="15dp"/>
</RelativeLayout>
</FrameLayout>
and my custom ArrayAdapter in my leaderboard class
public class LeaderAdapter extends ArrayAdapter<LeaderboardDM>{
ArrayList<LeaderboardDM> leaders;
int layoutResourceId;
public LeaderAdapter(Context context, int layoutResourceId, ArrayList<LeaderboardDM> leaders){
super(context, layoutResourceId, leaders);
this.leaders = new ArrayList<LeaderboardDM>();
this.leaders = leaders;
this.layoutResourceId = layoutResourceId;
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
ViewHolder viewHolder = null;
if(v == null){
v = getLayoutInflater().inflate(layoutResourceId, null, false);
viewHolder = new ViewHolder();
viewHolder.userImage = (ImageView) v.findViewById(R.id.user_image);
viewHolder.rank = (TextView) v.findViewById(R.id.rank);
viewHolder.userName = (TextView) v.findViewById(R.id.user_name);
viewHolder.score = (TextView) v.findViewById(R.id.score);
v.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) v.getTag();
}
LeaderboardDM lead = leaders.get(position);
if(lead != null){
//doesn't set user image yet
viewHolder.userName.setText(lead.user);
viewHolder.score.setText(String.valueOf(lead.points));
viewHolder.rank.setText("#"+String.valueOf(position+1));
}
return v;
}
class ViewHolder{
ImageView userImage;
TextView rank, userName, score;
}
}
and the leaderboardDM class
public class LeaderboardDM{
public String user;
public int points;
public String profilePicUrl;
public void setUserName(String user){
this.user = user;
}
public String getUserName(){
return user;
}
public void setPoints(int points){
this.points = points;
}
public int getPoints(){
return points;
}
public void setProfilePic(String url){
this.profilePicUrl = url;
}
public String getProfilePicUrl(){
return profilePicUrl;
}
}
The list gets sorted through using a comparator and again prints in order of their score. If anyone has an idea on how to create something like this please help point me in the right direction.
Thanks!
Edit:
Thanks to #Ridcully I was able to solve this issue.
The solution worked perfectly for anyone in the future that may do this, was to create a custom progress bar and get the drawable from the resources then set the ProgressDrawable to that drawable. From there I would set the width by setProgress(int width).
You could use a RelativeLayout and put a ProgressBar (with customized drawable) in the back. This way you can set the width of the bar by a simple setProgress().

Android: Checkbox absent if background present

I'm making an Activity with a ListView. Each row is made of two TextView and one CheckBox. The problem is that if I add the background attribute to the checkbox, it doesn't show in the row (not because it's transparent).
Does anybody have an explanation?
Actually it works fine either way on API 19, but the tests are made on the emulator with API 11 and I want to target API 8+.
Thank you in advance.
Image without the background attribute.
Image with the background attribute (You can see the strings going till the end of the frame):
[can't load images because of my reputation...]
The code is following.
Thank You in advance.
MainActivity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.lvListaMyLocationSalvate);
ArrayList<String[]> array = new ArrayList<String[]>();
array.add(new String[]{"asdasdasdasdasdasdasdasdasdasdasdasdasd","asdasdasdasdasdasdasdasdasdasdasdasdasd"});
array.add(new String[]{"asdasdasdasdasdasdasdasdasdasdasdasdasd","asdasdasdasdasdasdasdasdasdasdasdasdasd"});
Adapter arAdapter = new Adapter(this, array);
listView.setAdapter(arAdapter);
}
}
Adapter:
public class Adapter extends ArrayAdapter<String[]>{
Activity context;
ArrayList<String[]> array;
public Adapter(Activity activity, ArrayList<String[]> array) {
super(activity, R.layout.row, array);
this.context = activity;
this.array = array;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
view = context.getLayoutInflater().inflate(R.layout.row, null);
}
TextView tv1 = (TextView) view.findViewById(R.id.tvRow1);
TextView tv2 = (TextView) view.findViewById(R.id.tvRow2);
CheckBox cb = (CheckBox) view.findViewById(R.id.cb);
tv1.setText(((String[])(array.get(position)))[0]);
tv2.setText(((String[])(array.get(position)))[1]);
cb.setChecked(false);
return view;
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="#+id/lvListaMyLocationSalvate"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</RelativeLayout>
row.xml (CheckBox background attribute makes the difference)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<CheckBox
android:id="#+id/cb"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:background="#000000"
android:focusable="false"
android:focusableInTouchMode="false" />
<TextView
android:id="#+id/tvRow1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_toLeftOf="#id/cb"
android:textStyle="bold" />
<TextView
android:id="#+id/tvRow2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_below="#id/tvRow1"
android:layout_toLeftOf="#id/cb" />
</RelativeLayout>
The default background for the CheckBox is #android:drawable/btn_check_label_background. If you look at the drawable in your \platforms\android-11\data\res\drawable-hdpi folder, you'll find a nine-patch image that effectively defines the minimum height and width of your CheckBox and adds some left padding for the text such that the check box part of your CheckBox doesn't run into the text. By changing the background to a color (and not defining any text) there's no minimum height or width anymore, effectively hiding your CheckBox.
If you want a black background, you'll want to copy the btn_check_label_background image over to your res\drawable-hdpi folder, and modify it so that the bits you want black are black. See http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch for more details about how nine-patch drawables work.

onItemClickListener not firing on custom ArrayAdapter

I have an Activity that retrieves data from a web service. This data is presented in a ListView via an ArrayAdapter which inflates a RelativeLayout with three TextViews inside, nothing fancy and it work fine.
Now I want to implement a Details Activity that should be called when a user clicks an item in the ListView, sounds easy but I can't for the life of me get the onItemClickListener to work on my ArrayAdapter.
This is my main Activity:
public class Schema extends Activity {
private ArrayList<Lesson> lessons = new ArrayList<Lesson>();
private static final String TAG = "Schema";
ListView lstLessons;
Integer lessonId;
// called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// can we use the custom titlebar?
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
// set the view
setContentView(R.layout.main);
// set the title
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.titlebar);
// listview called lstLessons
lstLessons = (ListView)findViewById(R.id.lstLessons);
// load the schema
new loadSchema().execute();
// set the click listeners
lstLessons.setOnItemClickListener(selectLesson);
}// onCreate
// declare an OnItemClickListener for the AdapterArray (this doesn't work)
private OnItemClickListener selectLesson = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int i, long l) {
Log.v(TAG, "onItemClick fired!");
}
};
private class loadSchema extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
// ui calling possible
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Schema.this,"", "Please wait...", true);
}
// no ui from this one
#Override
protected Void doInBackground(Void... arg0) {
// get some JSON, this works fine
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
// apply to list adapter
lstLessons.setAdapter(new LessonListAdapter(Schema.this, R.layout.list_item, lessons));
}
My ArrayAdapter code:
// custom ArrayAdapter for Lessons
private class LessonListAdapter extends ArrayAdapter<Lesson> {
private ArrayList<Lesson> lessons;
public LessonListAdapter(Context context, int textViewResourceId, ArrayList<Lesson> items) {
super(context, textViewResourceId, items);
this.lessons = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_item, null);
}
Lesson o = lessons.get(position);
TextView tt = (TextView) v.findViewById(R.id.titletext);
TextView bt = (TextView) v.findViewById(R.id.timestarttext);
TextView rt = (TextView) v.findViewById(R.id.roomtext);
v.setClickable(true);
v.setFocusable(true);
tt.setText(o.title);
bt.setText(o.fmt_time_start);
rt.setText(o.room);
return v;
}
}// LessonListAdapter
The main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:screenOrientation="portrait"
>
<!-- student name -->
<TextView
android:id="#+id/schema_view_student"
android:text="Name" android:padding="4dip"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:gravity="center_vertical|center_horizontal"
style="#style/schema_view_student"
/>
<!-- date for schema -->
<TextView
android:id="#+id/schema_view_title"
android:layout_height="wrap_content"
android:layout_margin="0dip"
style="#style/schema_view_day"
android:gravity="center_vertical|center_horizontal"
android:layout_below="#+id/schema_view_student"
android:text="Date" android:padding="6dip"
android:layout_width="fill_parent"
/>
<!-- horizontal line -->
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:background="#55000000"
android:layout_below="#+id/schema_view_title"
/>
<!-- list of lessons -->
<ListView
android:id="#+id/lstLessons"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_below="#+id/schema_view_title"
/>
</RelativeLayout>
The list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60px"
android:padding="12dip">
<TextView
android:id="#+id/timestarttext"
android:text="09:45"
style="#style/LessonTimeStartText"
android:layout_width="60dip"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_height="fill_parent" android:gravity="center_vertical|right" android:paddingRight="6dip"/>
<TextView
android:id="#+id/titletext"
android:text="Test"
style="#style/LessonTitleText"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="#+id/timestarttext"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true" android:gravity="center_vertical|center_horizontal"/>
<TextView
android:id="#+id/roomtext"
android:text="123"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
style="#style/LessonRoomText"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:gravity="center_vertical" />
</RelativeLayout>
Been messing with this for the last couple of hours and I can't seem to get my head around what the problem is. My problem looks very similar to this question, but I'm not extending ListActivity, so I still don't know where my onListClickItem() should go.
UPDATE: Now I've puzzled with this for several days and still can't find the issue.
Should I rewrite the activity, this time extending ListActivity instead of Activity? Because it provides the onItemClick method itself and is probably easier to overwrite.
Or, should I bind a listener directly in each getView() in my ArrayAdapter? I believe I have read this is bad practice (I should do as I tried and failed in my post).
Found the bug - it seems to be this issue. Adding android:focusable="false" to each of the list_item.xml elements solved the issue, and the onclick is now triggered with the original code.
I've encountered the same issue and tried your fix but couldn't get it to work. What worked for me was adding android:descendantFocusability="blocksDescendants" to the <RelativeLayout> from the item layout xml, list_item.xml in your case. This allows onItemClick() to be called.
What worked for me :
1) Adding android:descendantFocusability="blocksDescendants" to Relative Layout tag.
The result is shown below :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants" >
2) Adding android:focusable="false" to every element in in list_item.xml
example :
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:focusable="false" />
Once I had a similar problem. Every list item had a text view and a checkbox, and just because the checkbox, the whole listitem wasn't 'enabled' to fire the event. I solved it by making a little trick inside the adapter when I was getting the view.
Just before returning the view I put:
v.setOnClickListener(listener);
(The object listener is an onItemClickListener I gave to the Adapter's constructor).
But I have to tell you, the problem is because the platform, it is a bug.
I had the same problem and I tried to solve it by adding
android:focusableInTouchMode="false"
android:clickable="false"
android:focusable="false"
to my item.xml but it still doesn't work !!! Infact I found the issue in the relative layout witch contains
android:focusableInTouchMode="true" android:focusable="true"
And when I removed it All things is ok
protected void onPostExecute(Void result) {
progressDialog.dismiss(); stLessons.setAdapter(new LessonListAdapter(Schema.this, R.layout.list_item, lessons));
//add this
ListView lv = getListView(); lv.setOnItemClickListener(new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
//do stuff
}
});
}

Categories

Resources