I programmed my app to be using listview and I create my addapter class to extend ArrayAddapter and also I create my getter class to get my words into the view I want to inflate but when I run the app it stops.
my addapter class code
package charpman.com.quakereport;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by DCharpMan on 4/19/2017.
* <p>
* class to populate each list view item
*/
public class QuakeAdapter extends ArrayAdapter<earthquakeClass> {
/**
* Constructor
*
* #param context The current context.
* #param earthquakeClass the array to be populated
*/
public QuakeAdapter(#NonNull Context context, ArrayList<earthquakeClass> earthquakeClass) {
super(context, R.layout.description_house, earthquakeClass);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View Customize = convertView;
if (Customize == null) {
Customize = LayoutInflater.from(getContext()).inflate(R.layout.description_house, parent, false);
}
earthquakeClass earthquakeClass = getItem(position);
TextView textView = (TextView) Customize.findViewById(R.id.text_magnitude);
textView.setText(earthquakeClass.getMagnitude());
textView.setTypeface(Typeface.MONOSPACE, 2 + 1);
TextView textView1 = (TextView) Customize.findViewById(R.id.text_loctaion);
textView1.setText(earthquakeClass.getLocation());
textView1.setTypeface(Typeface.SERIF, 1);
TextView textView2 = (TextView) Customize.findViewById(R.id.text_daye);
textView2.setText(earthquakeClass.getDate());
textView2.setTypeface(Typeface.DEFAULT_BOLD, 3);
return Customize;
}
}
my mainActivity.java code
package charpman.com.quakereport;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ArrayList<earthquakeClass> country = new ArrayList<earthquakeClass>();
country.add(new earthquakeClass("7.2", "nigeria", "23,07,2017"));
country.add(new earthquakeClass("7.2", "nigeria", "23,07,2017"));
country.add(new earthquakeClass("7.2", "nigeria", "23,07,2017"));
country.add(new earthquakeClass("7.2", "nigeria", "23,07,2017"));
country.add(new earthquakeClass("7.2", "nigeria", "23,07,2017"));
ListView listView = (ListView) findViewById(R.id.list_view);
QuakeAdapter quakeAdapter = new QuakeAdapter(this, country);
listView.setAdapter(quakeAdapter);
}
}
my getter class code
package charpman.com.quakereport;
/**
* Created by CharpMan on 4/19/2017.
* class to get the earthQuake details
* details includes Magnitude,location and date of earthquake
*/
public class earthquakeClass {
// globale variables that holds the earthquake information
String magnitude;
String location;
String date;
//contructor for the class takes in three params
// #param Magnitude tell the magnitude of the quake
// #params Location tells the location where the quake occured
// #params date tells the day of the quake
public earthquakeClass(String Magnitude, String Location, String Date){
magnitude = Magnitude;
location = Location;
date = Date;
}
// create public methods that returns each information
// method to the the magnitude
public String getMagnitude(){
return magnitude;
}
// methid to return the loctaion
public String getLocation(){
return location;
}
// methid to return the day of quake occurence
public String getDate (){
return date;
}
}
My MainActivity.xml code
<?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"
tools:context="charpman.com.quakereport.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#android:color/darker_gray"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="10dp"
android:text="Magnitude"
android:textAllCaps="true" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:paddingLeft="10dp"
android:text="Location"
android:textAllCaps="true" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:paddingLeft="20dp"
android:text="date"
android:textAllCaps="true" />
</LinearLayout>
<ListView
android:background="#android:color/secondary_text_light"
android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
xml code for the Layout I inflate in my Addapter class's GetView method
<?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"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/text_magnitude"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#android:color/white"
android:paddingLeft="14dp"
android:text="7.8" />
<TextView
android:id="#+id/text_loctaion"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#android:color/white"
android:gravity="center"
android:paddingLeft="5dp"
android:text="Nigeria"
android:typeface="serif" />
<TextView
android:id="#+id/text_daye"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:background="#android:color/white"
android:paddingLeft="25dp"
android:text="28,02,2017" />
</LinearLayout>
</LinearLayout>
I include a screenshot of my logcat
I was trying to read through the Code and i notice that ion my ListView code I added a backgroud tag
android:background="#android:color/secondary_text_light"
I ought to have define/copy the color code in project colors.xml and use it. Thanks
As per the error log i think in your XML file there is something which is not compatible as per your adapter or maybe you are using an object in your adapter which is not present in your XML file.
Related
So here is my problem, I got an API that gives me the lastest news of many sources. Each one of them goes with a cardview. The problem here is, while I'm using the swipeRefresh, it gets duplicated cardViews with the same news, like if I have 10 news, it duplicates to 20 with the same ones.
Here is my code where I apply the swipeRefresh:
package com.example.newsapp4;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.newsapp4.Model.Articles;
import com.example.newsapp4.Model.Headlines;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class bbcnews extends AppCompatActivity {
Adapter adapter;
Intent intencion;
RecyclerView recyclerView;
public static String source = "My Source";
public static String API_KEY = "My API Key";
SwipeRefreshLayout srl;
List<Articles> articles = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bbcnews);
srl = findViewById(R.id.swipeRefresh);
srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
retrieveJson(source, API_KEY);
}
});
recyclerView = findViewById(R.id.recyclerView1);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new Adapter(bbcnews.this,articles);
recyclerView.setAdapter(adapter);
retrieveJson(source, API_KEY);
}
public void retrieveJson(String source, String apiKey){
srl.setRefreshing(true);
Call<Headlines> call = ApiClient.getInstance().getApi().getHeadlines(source, apiKey);
call.enqueue(new Callback<Headlines>() {
#Override
public void onResponse(Call<Headlines> call, Response<Headlines> response) {
if(response.isSuccessful() && response.body().getArticles() != null){
srl.setRefreshing(false);
articles.clear();
articles = response.body().getArticles();
adapter.setArticles(articles);
}
}
#Override
public void onFailure(Call<Headlines> call, Throwable t) {
srl.setRefreshing(false);
Toast.makeText(bbcnews.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public String getCountry(){
Locale locale = Locale.getDefault();
String country = locale.getCountry();
return country.toLowerCase();
}
public void aPerfil(View vista){
intencion = new Intent(this, profile_activity.class);
startActivity(intencion);
}
}
I don't think that I need to put the xml code with the progressbar and the swipeRefresh but here are both:
This one is the Items.xml where I created the cardView:
<?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="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardElevation="4dp"
android:id="#+id/cardView"
app:cardCornerRadius="10dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="#+id/loader"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/image"
android:scaleType="centerCrop"
android:src="#drawable/img"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TITLE"
android:textSize="20dp"
android:padding="10dp"
android:fontFamily="#font/g_bold"
android:textColor="#color/white"
android:id="#+id/tvTitle"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Source"
android:textSize="16dp"
android:padding="10dp"
android:ems="15"
android:fontFamily="#font/g_light"
android:textColor="#color/white"
android:id="#+id/tvSource"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="#font/g_light"
android:gravity="right"
android:text="Date"
android:textColor="#color/white"
android:padding="10dp"
android:textSize="16dp"
android:id="#+id/tvDate"/>
</LinearLayout>
</FrameLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
And here the one with the swipeRefresh in the recyclerView:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
tools:context=".bbcnews">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DINGO BBC NEWS"
android:textColor="#color/black"
android:textSize="20sp"
android:fontFamily="#font/g_bold"
android:background="#color/white"
android:padding="10dp"
android:textAlignment="center"/>
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:columnCount="2"
android:paddingLeft="20dp"
android:paddingRight="5dp"
android:background="#drawable/black_background"
android:rowCount="2">
<EditText
android:id="#+id/editTextTextPersonName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Search"
android:textColor="#color/grey"
android:textColorHint="#color/grey"
android:padding="5dp"
android:layout_column="0"
android:background="#drawable/black_background"
android:layout_row="0"
android:layout_columnWeight="1"
android:inputType="textPersonName" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="20dp"
android:background="#drawable/black_background"
android:drawableRight="#drawable/ic_baseline_search_24"
android:layout_column="1"
android:layout_row="0"/>
</GridLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/swipeRefresh">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:id="#+id/recyclerView1"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
Also this is my adapter.java code:
package com.example.newsapp4;
import android.content.Context;
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.newsapp4.Model.Articles;
import com.squareup.picasso.Picasso;
import java.util.List;
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
Context context;
List<Articles> articles;
public Adapter(Context context, List<Articles> articles) {
this.context = context;
this.articles = articles;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
final Articles a = articles.get(position);
String imageUrl = a.getUrlToImage();
holder.tvTitle.setText(a.getTitle());
holder.tvSource.setText(a.getSource().getName());
holder.tvDate.setText(a.getPublishedAt());
Picasso.with(context).load(imageUrl).into(holder.imageView);
}
#Override
public int getItemCount() {
return articles.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvTitle,tvSource,tvDate;
ImageView imageView;
CardView cardView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvTitle = itemView.findViewById(R.id.tvTitle);
tvSource = itemView.findViewById(R.id.tvSource);
tvDate = itemView.findViewById(R.id.tvDate);
imageView = itemView.findViewById(R.id.image);
cardView = itemView.findViewById(R.id.cardView);
}
}
public void setArticles(List<Articles> articles) {
this.articles.addAll(articles);
int count = getItemCount();
notifyItemRangeInserted(count, count + articles.size());
}
}
Thanks for your time!
// Clear adapter list before add to list.
public void setArticles(List<Articles> articles) {
if(this.articles!=null && this.articles.size()>0)
this.articles.clear();
this.articles.addAll(articles);
int count = getItemCount();
notifyItemRangeInserted(count, count + articles.size());
}
From what I can understand in your code is on the success of API call after Swipe Refresh which is this section here
articles.clear();
articles = response.body().getArticles();
adapter.setArticles(articles);
You are here clearing the article inside your activity, but the thing is inside your Adapter there is already another list of articles, you are not clearing them.
And then when you make the adapter.setArticles(articles); call, inside the following function, your articles get added to the already existing list of articles and thus, the duplicate list.
public void setArticles(List<Articles> articles) {
this.articles.addAll(articles);
int count = getItemCount();
notifyItemRangeInserted(count, count + articles.size());
}
To fix this you can make the following modifications to your function.
public void setArticles(List<Articles> articles, boolean clearAll) {
if(clearAll){ this.articles.clear(); }
this.articles.addAll(articles);
notifyDataSetChanged();
}
And then modify your function call as follows
adapter.setArticles(articles, true);
That way when the Boolean is true, it will clear the existing list. Also I would suggest you to replace the insert call with data set change call. Else you can make a separate function all together for adding elements and for clearing existing elements.
I'm looking to implement a search function. When it runs, logcat is telling me:
E/RecyclerView: No adapter attached; skipping layout.
I have searched SO and the net and the answers tell me that I need to set the adapter and the linear layout manager. As you will see with my code, I set both. Alex Mamo's (#AlexMamo) work on here seems to point me in the right direction but I'm still getting the error.
My Activity
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.MyApp.Objects.ParticipantsObject;
import com.MyApp.R;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
public class ParticipantsActivity extends AppCompatActivity {
private EditText mSearchField;
private ImageButton mSearchBtn;
private RecyclerView mResultList;
private DatabaseReference mUserDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_neighbors);
mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Participants");
mSearchField = (EditText) findViewById(R.id.search_field);
mSearchBtn = (ImageButton) findViewById(R.id.search_btn);
mResultList = (RecyclerView) findViewById(R.id.result_list);
mResultList.setHasFixedSize(true);
mResultList.setLayoutManager(new LinearLayoutManager(this));
mSearchBtn.setOnClickListener(view -> {
String searchText = mSearchField.getText().toString();
firebaseUserSearch(searchText);
});
}
private void firebaseUserSearch(String searchText) {
Toast.makeText(ParticipantsActivity.this, "Started Search", Toast.LENGTH_LONG).show();
Query firebaseSearchQuery = mUserDatabase.orderByChild("name").startAt(searchText);
FirebaseRecyclerOptions<ParticipantsObject> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<ParticipantsObject>()
.setQuery(firebaseSearchQuery, ParticipantsObject.class)
.build();
class UserHolder extends RecyclerView.ViewHolder {
private TextView imageThumbTextView, nameTextView
UserHolder(View itemView) {
super(itemView);
imageThumbTextView = itemView.findViewById(R.id.profile_image);
nameTextView = itemView.findViewById(R.id.name_text);
}
void setUsers(ParticipantsObject participantsObject) {
String imageThumb = driverObject.getThumb_image();
imageThumbTextView.setText(imageThumb);
String name = participantsObject.getName();
nameTextView.setText(name);
}
}
FirebaseRecyclerAdapter<ParticipantsObject, UserHolder> firebaseRecyclerAdapter;
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ParticipantsObject, UserHolder>(firebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(#NonNull UserHolder userHolder, int position, #NonNull ParticipantsObject participantsObject) {
userHolder.setUsers(participantsObject);
}
#Override
public UserHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new UserHolder(view);
}
};
mResultList.setAdapter(firebaseRecyclerAdapter);
firebaseRecyclerAdapter.startListening();
}
}
My Activity XML file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="#ffffff"
tools:context="com.MyApp.ParticipantsActivity">
<TextView
android:id="#+id/heading_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="30dp"
android:text="Firebase Search"
android:textColor="#555555"
android:textSize="24sp" />
<EditText
android:id="#+id/search_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/heading_label"
android:layout_below="#+id/heading_label"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_toStartOf="#+id/search_btn"
android:background="#drawable/search_layout"
android:ems="10"
android:hint="Search here"
android:inputType="textPersonName"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:textColor="#999999"
android:textSize="16sp" />
<ImageButton
android:id="#+id/search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/search_field"
android:layout_alignParentEnd="true"
android:layout_alignTop="#+id/search_field"
android:layout_marginRight="30dp"
android:background="#android:color/background_light"
app:srcCompat="#mipmap/search_button" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/result_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/search_field"
android:layout_marginTop="50dp">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
My list layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginTop="20dp"
app:srcCompat="#mipmap/ic_default_user" />
<TextView
android:id="#+id/name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="14dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="213dp"
android:layout_marginRight="20dp"
android:layout_toEndOf="#+id/profile_image"
android:text="Username"
android:textColor="#555555"
android:textSize="16sp" />
</RelativeLayout>
Any ideas or advice would be much appreciated.
Your code is setting the adapter only after a button is pushed. Because you didn't set it before the first time the RecyclerView needed to render itself on screen, it's going to warn you about that with the message you see in the log. The RecyclerView must have an adapter attached at the time of rendering in order for it to display anything.
I am trying to create a custom layout for list view in android studio. I was able to successfully get image in the in ListView on runtime but wasn't able to print text in the list view . When i run my program in emulator it runs without any error but it doesn't show any text it only shows image from drawables.
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
private final static String[] names={"A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","A",
"A","A","A","A","A","A","A","A","A","A","A","A","A","A",};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView ls = findViewById((R.id.customlistview));
ls.setAdapter(new CustomListAdapter(getApplicationContext(),names,R.drawable.za));
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="#+id/customlistview"
android:layout_width="409dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
CustomListAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomListAdapter extends BaseAdapter {
private final Context context;
private final String[] names;
private final int image;
private final LayoutInflater layoutInflater;
public CustomListAdapter(Context context,String[] names,int image) {
this.context=context;
this.image=image;
this.names=names;
layoutInflater= (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return names.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rootview;
rootview = layoutInflater.inflate(R.layout.list_item_layout, null);
TextView tv= rootview.findViewById(R.id.textView);
ImageView iv=rootview.findViewById(R.id.imageView);
tv.setText(names[position]);
iv.setImageResource(image);
return rootview;
}
}
list_item_layout.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:height="70dp"
android:gravity="center"
android:text="TextView"
android:textSize="18sp" />
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_weight="2"
app:srcCompat="#mipmap/ic_launcher" />
</LinearLayout>
The issue is in your list_item_layout file. There is an issue with match_parent in your layout try using below code
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="horizontal">
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:height="70dp"
android:gravity="center"
android:text="TextView"
android:textSize="18sp" />
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_weight="2"
app:srcCompat="#mipmap/ic_launcher" />
The problem was caused by the text colour , changing the colour of textview text in list_item_layout resolved the issue.
This question already has answers here:
Null pointer Exception - findViewById()
(12 answers)
findViewById returns null
(4 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I've created a Location class and when I click on Cinemas in MainActivity, I want to open another activity that contains the list of Location objects. For this goal I have created a custom location_list_item layout file and a custom ArrayAdapter. For some reason, when I click on Cinemas, my app crashes. Why?
MainActivity.java
package com.example.android.tourguide;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View cinemasView = findViewById(R.id.cinemas_layout);
cinemasView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
CinemasActivity.class);
startActivity(intent);
}
});
}
}
activity_main.xml
<?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:background="#fff8e1"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/main_activity_title"
android:textSize="30sp"
android:textStyle="bold"
android:textColor="#android:color/black"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"/>
<LinearLayout
android:id="#+id/cinemas_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/category_cinemas"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/category_cinemas"
android:textSize="25sp"
android:textColor="#android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray" />
<LinearLayout
android:id="#+id/restaurants_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/category_restaurants"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/category_restaurants"
android:textSize="25sp"
android:textColor="#android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray" />
<LinearLayout
android:id="#+id/gyms_layout"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/category_gyms"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/category_gyms"
android:textSize="25sp"
android:textColor="#android:color/white"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray" />
<LinearLayout
android:id="#+id/parks_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#4a148c">
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/category_parks"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/category_parks"
android:textSize="25sp"
android:textColor="#android:color/white"/>
</LinearLayout>
</LinearLayout>
location_category_list_item.xml
<?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="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/location_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/location_hours_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Hours"
android:textStyle="bold"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/location_working_days"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="Every Day" />
<TextView
android:id="#+id/location_working_hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
tools:text="09:00 – 00:00" />
</LinearLayout>
<TextView
android:id="#+id/location_address_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Address"
android:textStyle="bold"/>
<TextView
android:id="#+id/location_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="09:00 – 00:00" />
<TextView
android:id="#+id/location_phone_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Phone"
android:textStyle="bold"/>
<TextView
android:id="#+id/location_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="+7 (555) 555-55-55" />
</LinearLayout>
Location.java
package com.example.android.tourguide;
import androidx.annotation.NonNull;
public class Location {
private int mImageResourceId;
private String mAddress;
private String mPhone;
private String mWorkingDays;
private String mWorkingHours;
public Location(int imageResourceId, String address, String phone,
String workingDays, String workingHours) {
mImageResourceId = imageResourceId;
mAddress = address;
mPhone = phone;
mWorkingDays = workingDays;
mWorkingHours = workingHours;
}
public int getImageResourceId() {
return mImageResourceId;
}
public String getAddress() {
return mAddress;
}
public String getPhone() {
return mPhone;
}
public String getWorkingDays() {
return mWorkingDays;
}
public String getWorkingHours() {
return mWorkingHours;
}
#NonNull
#Override
public String toString() {
return mImageResourceId + mAddress + mWorkingDays + mWorkingDays + mPhone;
}
}
LocationAdapter.java
package com.example.android.tourguide;
import android.app.Activity;
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 java.util.ArrayList;
public class LocationAdapter extends ArrayAdapter<Location> {
/**
* This is our own custom constructor (it doesn't mirror a superclass constructor).
* The context is used to inflate the layout file, and the list is the data we want
* to populate into the lists.
*
* #param context The current context. Used to inflate the layout file.
* #param locations A List of Location objects to display in a list
*/
public LocationAdapter(Activity context, ArrayList<Location> locations) {
// Here, we initialize the ArrayAdapter's internal storage for the context and the list.
// the second argument is used when the ArrayAdapter is populating a single TextView.
// Because this is a custom adapter for one ImageView and 4 TextViews, the adapter is not
// going to use this second argument, so it can be any value. Here, we used 0.
super(context, 0, locations);
}
/**
* Provides a view for an AdapterView (ListView, GridView, etc.)
*
* #param position The position in the list of data that should be displayed in the
* list item view.
* #param convertView The recycled view to populate.
* #param parent The parent ViewGroup that is used for inflation.
* #return The View for the position in the AdapterView.
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null)
{
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.location_category_list_item, parent,
false);
}
// Get the {#link Location} object located at this position in the list
Location currentLocation = getItem(position);
// Find the ImageView in the location_category_list_item.xml layout
// with the ID location_image
ImageView image = listItemView.findViewById(R.id.location_image);
// Get the image resource ID from the current Location object and
// set the image to imageView
image.setImageResource(currentLocation.getImageResourceId());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_working_days
TextView workingDaysTextView = listItemView.findViewById(R.id.location_working_days);
// Get the working days from the current Location object and
// set this text on the workingDaysTextView
workingDaysTextView.setText(currentLocation.getWorkingDays());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_working_hours
TextView workingHoursTextView = listItemView.findViewById(R.id.location_working_hours);
// Get the working hours from the current Location object and
// set this text on the workingHoursTextView
workingHoursTextView.setText(currentLocation.getWorkingHours());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_address
TextView addressTextView = listItemView.findViewById(R.id.location_address);
// Get the address from the current Location object and
// set this text on the addressTextView
addressTextView.setText(currentLocation.getAddress());
// Find the TextView in the location_category_list_item.xml layout
// with the ID location_phone
TextView phoneTextView = listItemView.findViewById(R.id.location_phone);
// Get the address from the current Location object and
// set this text on the phoneTextView
phoneTextView.setText(currentLocation.getPhone());
// Return the whole list item layout
// so that it can be shown in the ListView
return listItemView;
}
}
CinemasActivity.java
package com.example.android.tourguide;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
public class CinemasActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.location_category_list_item);
//Create a list of cinemas
final ArrayList<Location> locations = new ArrayList<>();
locations.add(new Location(R.drawable.cinemas_byl,
"Zhukova mikrorayon, 38",
"+7 (929) 002-20-09",
"Every Day",
"09:00 – 00:00"));
locations.add(new Location(R.drawable.cinemas_charly,
"Ol'minskogo mikrorayon, 17",
"+7 (472) 523-34-56",
"Every Day",
"09:30 – 02:00"));
locations.add(new Location(R.drawable.cinemas_cinema_5,
"Molodezhnyy Proyezd, 10",
"+7 (472) 523-37-27",
"Every Day",
"09:00 – 00:00"));
// Create an {#link LocationAdapter}, whose data source is a list of
// {#link Locations}. The adapter knows how to create list item views
// for each item in the list.
LocationAdapter locationAdapter = new LocationAdapter(this, locations);
// Get a reference to the ListView, and attach the adapter to the listView.
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(locationAdapter);
}
}
Probably you set wrong layout in your CinemasActivity.
setContentView(R.layout.location_category_list_item);
R.layout.location_category_list_item is item view for your ListView.
There is no ListView in location_category_list_item which causes the crash
So I have a for loop that I want to output a new line in a textview every single time it goes through. However, I am not sure if that is possible. I have TableLayout in there but it put the items vertically instead of horizontally. I thought about ListView but not sure how to set the text of it.
Here is my code
import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route;
import org.joda.time.DateTime;
import org.w3c.dom.Text;
import java.io.IOException;
import java.util.Map;
import okhttp3.Request;
import okhttp3.Response;
/**
* Created by James Singleton on 8/13/2016.
*/
public class WeeklyDrives extends Fragment implements APIRequestsUtil.APIRequestResponseListener
{
View myView;
Map<String, Route> drives;
private TextView driveNumber;
private TextView driveDistance;
private TextView driveTime;
private TextView driveNumList;
private TextView driveDistList;
private TextView driveTimeList;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.weekly_drives, container, false);
APIRequestsUtil.setOnNetWorkListener(this);
return myView;
}
private void populateView() {
this.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
drives = APIRequestsUtil.getRoutes();
driveNumber = (TextView) myView.findViewById(R.id.Drive_Number);
driveDistance = (TextView) myView.findViewById(R.id.Drive_Distance);
driveTime = (TextView) myView.findViewById(R.id.Drive_Time);
driveNumber.setText("Drive Num.");
driveDistance.setText("Distance");
driveTime.setText("Time");
int driveNum = 0;
for (Map.Entry drive : drives.entrySet()) {
TableRow tr = new TableRow(getActivity());
Route route = (Route) drive.getValue();
tr.setId(driveNum++);
//tr.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
DateTime startTime = new DateTime(route.getStart_time());
DateTime endTime = new DateTime(route.getEnd_time());
driveNumList = (TextView) myView.findViewById(R.id.Drive_Number_List);
driveDistList = (TextView) myView.findViewById(R.id.Drive_Distance_List);
driveTimeList = (TextView) myView.findViewById(R.id.Drive_Time_List);
driveNumList.setText(driveNumList.getText().toString() + String.valueOf(driveNum) + System.getProperty("line.separator"));
driveDistList.setText(driveDistList.getText().toString() + Float.parseFloat(route.getLen()) / 1000 + " km" + System.getProperty("line.separator"));
driveTimeList.setText(driveTimeList.getText().toString() + ((endTime.getMillis() - startTime.getMillis())/ 1000)/60 + " min" + System.getProperty("line.separator"));
}
}
});
}
#Override
public void onFailure(Request request, Throwable throwable) {
}
#Override
public void onResponse(Response response) {
populateView();
}
}
Here is my XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Header aligned to top -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/header"
android:gravity="center"
android:background="#FC9">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Number"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Distance"
android:layout_toRightOf="#+id/Drive_Number"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Time"
android:layout_toRightOf="#+id/Drive_Distance"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
</RelativeLayout>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"
android:background="#005"
android:layout_below="#+id/header"
android:id="#+id/scrollableContents">
<!--<TableLayout-->
<!--android:id="#+id/fragment1_tlayout"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:stretchColumns="0,1">-->
<!--</TableLayout>-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Number_List"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Distance_List"
android:layout_toRightOf="#+id/Drive_Number_List"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Time_List"
android:layout_toRightOf="#+id/Drive_Distance_List"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC"/>
</LinearLayout>
</ScrollView>
</RelativeLayout>
drive.entrySet() output
What is this:[2016-07-11--08-52-18=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#12a862, 2016-07-11--09-37-46=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#50bbdf3, 2016-07-11--18-54-22=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#6d21ab0, 2016-07-12--09-15-59=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#fb72d29, 2016-07-12--09-29-29=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#776e8ae, 2016-07-12--09-33-03=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#d1a464f, 2016-07-12--09-38-56=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#5b631dc, 2016-07-12--09-41-08=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#dec72e5, 2016-07-12--09-42-39=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#acce1ba, 2016-07-12--09-44-33=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#5def86b, 2016-07-12--09-49-31=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#d628fc8, 2016-07-12--09-54-06=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#7765861, 2016-07-12--19-04-34=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#8575f86, 2016-07-12--19-39-20=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#3f2b047, 2016-07-12--19-40-27=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#df4e074, 2016-07-12--19-41-28=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#b5f199d, 2016-07-13--08-45-17=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#db9ee12, 2016-07-13--09-01-32=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#2a009e3, 2016-07-13--15-02-04=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#9b98fe0, 2016-07-14--08-46-22=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#518b299, 2016-07-14--19-22-46=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#d44d95e, 2016-07-14--19-34-02=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#d3f613f, 2016-07-14--20-16-47=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#957ca0c, 2016-07-15--08-36-28=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#b38df55, 2016-07-15--09-52-32=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#c012d6a, 2016-07-15--12-09-57=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#252d25b, 2016-07-15--12-15-07=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#6bd7af8, 2016-07-15--15-36-10=com.example.jamessingleton.chffrapi.com.examples.jamessingleton.chffrapi.data.Route#df51bd1,
Add android:inputType="textMultiLine" to the TextView in the XML.
And add data into TextView like this:
driveNumList.setText(driveNumList.getText().toString() + String.valueOf(driveNum) + System.getProperty("line.separator"));
And so on.
Edit: you can use "\n" instead of System.getProperty("line.separator") for adding the new line character.
I would recommend a ListView for this type of thing so that it is automatically scrollable, uses View recycling to maintain efficiency, cleans up your code and organizes it into digestible segments.
To use a ListView, you first need to add it to your main XML file. So that would become the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Header aligned to top -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/header"
android:gravity="center"
android:background="#FC9">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Number"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Distance"
android:layout_toRightOf="#+id/Drive_Number"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Drive_Time"
android:layout_toRightOf="#+id/Drive_Distance"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#000"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"
android:background="#005"
android:layout_below="#+id/header"
android:id="#+id/scrollableContents">
<ListView
android:id="#+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
</RelativeLayout>
Following that, you need to create your ListView adapter class. It is what handles what each individual list item's data is (the thing inside your for-loop).
Here is one that you might use, although you may have to make your own tweaks and import more of your own classes, add your package name to the top, etc.
So create a new Java class called DriveListAdapter.java and place the following code into it:
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
public class DriveListAdapter extends ArrayAdapter<Map.Entry> {
private final Activity context;
// you may need to change List to something else (whatever is returned from drives.entrySet())
private final List<Map.Entry> drives;
// may also need to change List here (above comment)
public DriveListAdapter(Activity context, List<Map.Entry> drives) {
super(context, R.layout.drive_list_item, drives);
this.context = context;
this.drives = drives;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.drive_list_item, null, true);
Map.Entry drive = this.drives.get(position);
// position is the index of the drives.entrySet() array
int driveNum = position + 1;
// need to import your Route class
Route route = (Route) drive.getValue();
// need to import your DateTime class
DateTime startTime = new DateTime(route.getStart_time());
DateTime endTime = new DateTime(route.getEnd_time());
TextView driveNumList = (TextView) rowView.findViewById(R.id.Drive_Number_List);
TextView driveDistList = (TextView) rowView.findViewById(R.id.Drive_Distance_List);
TextView driveTimeList = (TextView) rowView.findViewById(R.id.Drive_Time_List);
driveNumList.setText(String.valueOf(driveNum));
driveDistList.setText(Double.parseDouble(route.getLen()) / 1000 + " km");
driveTimeList.setText((endTime.getMillis() - startTime.getMillis())/ 1000 + " s");
return rowView;
}
}
Then, create a new layout file, which will be what the individual list item looks like. This layout is rendered for each and every drive in the list. You can adjust this layout file so that everything is aligned properly. I gave an example of how to do that (create a layout file called drive_list_item.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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC"
android:text="Medium Text"
android:id="#+id/Drive_Number_List"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC"
android:text="Medium Text"
android:id="#+id/Drive_Distance_List"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:textSize="20sp"
android:textColor="#CCCCCC"
android:text="Medium Text"
android:id="#+id/Drive_Time_List"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
And lastly, you just need to populate that ListView you created in the first step with this new adapter class.
So use the following method (populates the ListView instead of using the for loop):
private void populateView() {
this.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
drives = APIRequestsUtil.getRoutes();
driveNumber = (TextView) myView.findViewById(R.id.Drive_Number);
driveDistance = (TextView) myView.findViewById(R.id.Drive_Distance);
driveTime = (TextView) myView.findViewById(R.id.Drive_Time);
driveNumber.setText("Drive Number");
driveDistance.setText("Drive Distance");
driveTime.setText("Drive Time");
// edit: you need to generate your List data from the entrySet
// the ArrayAdapter cannot take a Set argument - needs to be a List
List<Map.Entry> list = new ArrayList<Map.Entry>();
for (Map.Entry drive : drives.entrySet()) {
list.add(drive);
}
// populate the ListView
// may need to change "getActivity()" to something else
// this constructor needs the "this" context of the activity
DriveListAdapter drivesListAdapter = new DriveListAdapter(getActivity(), list);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(drivesListAdapter);
}
});
}
first of all you use LinearLayout instead of TableLayoyt
<LinearLayout
android:id="#+id/llMainLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
try this code
LinearLayout llMain=(LinearLayout) myView.findViewById(R.id.llMainLayout);
for (Map.Entry drive : drives.entrySet()) {
LinearLayout tr = new LinearLayout(getActivity());
tr.setOrientation(1); // horizontal
Route route = (Route) drive.getValue();
tr.setId(driveNum++);
// set params
DateTime startTime = new DateTime(route.getStart_time());
DateTime endTime = new DateTime(route.getEnd_time());
TextView driveNumList = new TextView();
TextView driveDistList = new TextView();
TextView driveTimeList = new TextView();
driveNumList.setText(String.valueOf(driveNum));
driveDistList.setText(Double.parseDouble(route.getLen()) / 1000 + " km");
driveTimeList.setText((endTime.getMillis() - startTime.getMillis())/ 1000 + " s");
tr.addView(driveNumList);
tr.addView(driveDistList);
tr.addView(driveTimeList);
llMain.addView(tr);
}
}