Currently I'm a beginner in android. Right now I'm trying to make my ListView item open a layout which contain WebView when any item is clicked. Each item will direct to a different page. But I'm not sure how can I achieve this. This is my code.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.activity_listview, null);
}
FeedItem p = getItem(position);
if (p != null) {
TextView tt1 = (TextView) v.findViewById(R.id.title_text);
TextView tt2 = (TextView) v.findViewById(R.id.date_text);
if (tt1 != null) {
tt1.setText(p.getTitle());
}
if (tt2 != null) {
tt2.setText(p.getPubDate());
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
FeedItem q = getItem(position);
if(q.getLink() != null){
//Toast.makeText(getContext(), "" + q.getLink(), Toast.LENGTH_SHORT).show();
}
}
});
}
return v;
}
Your Question is totally opinion based. both can be used as per app's requirement.
Default Browser
it is easy to use just 4 or file lines and you are good to go. but it gets user out of application.
How to use it.
Intent intent= new Intent(Intent.ACTION_VIEW,Uri.parse(YOUR_URL));
startActivity(intent);
WebView
can be used as a part of application. you need to create on activity containing webview and call intent from where you want to open webview.
Example
Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webView" />
</RelativeLayout>
java
public class WebViewActivity extends Activity {
private WebView wv1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wv1=(WebView)findViewById(R.id.webView);
wv1.getSettings().setLoadsImagesAutomatically(true);
wv1.getSettings().setJavaScriptEnabled(true);
wv1.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
wv1.loadUrl(your_url);
}
}
and just call this from where you want to open Webview.
Intent intent= new Intent(MainActivity.this,WebViewActivity.class);
startActivity(intent);
refer this link.
I hope it is clear.
You can modify little bit according to your requirement and need to put your import your package.
if(q.getLink() != null){
Intent intent = new Intent(getActivity(), BrowserActivity.class);
intent.putExtra("url", q.getLink());
startActivity(intent);
}
BrowserActivity
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.Toast;
import com.yourproject.R;
public class BrowserActivity extends FragmentActivity {
WebView webview;
public BrowserActivity() {
// Required empty public constructor
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.comment_detail);
String url = getIntent().getStringExtra("url");
Log.d("URL ", url);
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setBuiltInZoomControls(true);
webview.getSettings().setSupportZoom(true);
webview.loadUrl(url);
webview.setWebViewClient(new WebViewClient() {
public void onPageStarted(WebView view, String url) {
}
public void onPageFinished(WebView view, String url) {
// do your stuff here
MyApplication.hideTransparentProgressDialog();
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(CommentDetails.this, description, Toast.LENGTH_SHORT).show();
}
});
}
}
comment_detail.xml
<include
android:id="#+id/headerTV"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
layout="#layout/title_bar_layout_job_info" />
<WebView
android:layout_below="#+id/headerTV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webview">
</WebView>
To open browser use intent:
String url = "https://www.google.com/";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
and for webview :
XML Code:
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
JAVA Code:
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class WebViewActivity extends Activity {
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://www.google.com");
}
}
you can also load your own html file on WebView.
Related
I want to open a atctivity, that includes a browser, when i press the button 5 times.
Here is my MainActivity.java:
package de.gamingwave.browser;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static int druecken = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setDruecken(getDruecken() + 1);
System.out.println(getDruecken());
if (druecken == 5){
Intent activity2Intent = new Intent(getApplicationContext(), browser.class);
startActivity(activity2Intent);
}
}
});
}
public static int getDruecken() {
return druecken;
}
public static void setDruecken(int druecken) {
MainActivity.druecken = druecken;
}
}
Here is the browser.java:
package de.gamingwave.browser;
import android.annotation.SuppressLint;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.webkit.DownloadListener;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
public class browser extends AppCompatActivity {
// Declare View object references
EditText etUrl;
Button btnGo;
WebView webView;
ProgressBar progressBar;
ProgressDialog progressDialog;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
// Instantiate View objects
etUrl = findViewById(R.id.etUrl);
btnGo = findViewById(R.id.btnGo);
webView = findViewById(R.id.webview);
progressBar = findViewById(R.id.progressBar);
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading Please Wait...");
// Create a WebSettings object
// Set Zoom Controls
webView.getSettings().setBuiltInZoomControls(true);
// JavaScript is by default turned off in WebView. To enable JavaScript we can call
// setJavaScriptEnabled() method on webSettings object and pass true as parameter.
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAllowFileAccess(true);
/*
Now, when the user clicks a link from a web page in your WebView, the
default behavior for Android is to launch an application that handles
URLs. Typically, system's default web browser opens and loads the
destination URL. However, you can override this behavior for your
WebView, so that links open within your WebView and hence within the app.
You can then allow the user to navigate backward and forward through their web page history
that's maintained by your WebView. To accomplish this, we need to create a subclass of
WebViewClient and override it's shouldOverrideUrlLoading() method. Let's do that.
*/
webView.setWebViewClient(new MyWebViewClient());
if (!checkConnection()) {
showDialog();
}
// Attach OnClickListener with the Button
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Get the text from EditText
String url = etUrl.getText().toString().trim();
// If entered url doesn't start "http://" or "https://" we need to append it
// before the url.
if (!url.startsWith("http://") || !url.startsWith("https://")) {
url = "https://" + url;
}
// To load the webView with the url we need to call loadUrl() method
// of the WebView class, passing url as parameter.
webView.loadUrl(url);
}
});
webView.setWebChromeClient(new WebChromeClient() {
#Override
public void onProgressChanged(WebView view, int newProgress) {
setTitle("Loading...");
progressBar.setProgress(newProgress);
progressDialog.show();
if (newProgress == 100) {
setTitle(webView.getTitle());
progressDialog.dismiss();
}
super.onProgressChanged(view, newProgress);
}
});
webView.setDownloadListener(new MyDownLoadListener());
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// When you return false you're telling Android not to override; let WebView
// load the page
return false;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressBar.setVisibility(View.VISIBLE);
webView.setVisibility(View.GONE);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
webView.setVisibility(View.VISIBLE);
}
}
/* Run the application. (pause)
Let's specify a url in the EditText field and press the ENTER button to launch the website.
But before that please make sure that you are connected to the internet.
The site looks good in WebView.
As you can see, the url loads properly in WebView but if we click the Back button,
the app gets closed even though we’ve navigated through a few pages within the WebView itself.
Let's see how we can handle navigation in WebView with Back Button.
To go through the browsing history on pressing the Back button we need to override
onBackPressed() method as follows.
*/
#Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to Exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
// The WebView maintains a browsing history just like a normal browser.
// If there is no history then it will result in the default behavior of the Back button i.e.
// closing the app.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navPrev:
onBackPressed();
break;
case R.id.navNext:
if (webView.canGoForward()) {
webView.goForward();
}
break;
case R.id.navReload:
checkConnection();
}
return super.onOptionsItemSelected(item);
}
private boolean checkConnection() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
if (capabilities != null) {
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return true;
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return true;
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return true;
}
}
} else {
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
return true;
}
}
}
return false;
}
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Connect to WIFI or Exit")
.setCancelable(false)
.setPositiveButton("Connect to WIFI", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
})
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public class MyDownLoadListener implements DownloadListener {
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
if (url != null) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
}
}
}
Here is the activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:text="Senden"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:backgroundTint="#1BB500"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="Name"
android:ems="10"
android:id="#+id/editTextTextPersonName" tools:layout_editor_absoluteY="127dp"
tools:layout_editor_absoluteX="105dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And here is the activity_browser.java:
<?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=".browser"
android:padding="10dp">
<!-- Lets design the layout -->
<!-- Create a horizontal LinearLayout to display the EditText and the ENTER Button. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/etUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="9"
android:ems="10"
android:maxLines="1"
android:hint="Enter Url"
android:inputType="textPersonName"
android:minHeight="52dp"
android:drawableLeft="#drawable/ic_baseline_search_24"/>
<Button
android:id="#+id/btnGo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#0070c7"
android:textColor="#android:color/white"
android:layout_weight="1"
android:text="Go" />
</LinearLayout>
<!-- Add a RelativeLayout to contain a ProgressBar and a WebView
that fills the rest of the screen. -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webview"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>
What's wrong with this code?
Thank's for helping.
The button should open a new browser activity.
I have an android app that has two fragments that pass data from fragmentA to fragmentB. I can load all the data correctly but when I change the screen orientation it all reloads. I have set up the onSaveInstanceState and onViewStateRestored methods in the fragment I want to keep the state in, but nothing stays when the screen orientation changes.
The main problem that needs to be fixed is when text is loaded into the TextView in FragmentB - it needs to stay there when the screen orientation is changed.
MainActivity.Java
package com.example.tourguide;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements FragmentA.FragmentAListener, FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commitNow();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onInputASent(CharSequence input) {
fragmentB.updateEditText(input);
}
#Override
public void onInputBSent(CharSequence input) {
fragmentA.updateEditText(input);
}
}
FragmentA.Java
package com.example.tourguide;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.ListFragment;
public class FragmentA extends ListFragment implements AdapterView.OnItemClickListener {
private FragmentAListener listener;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String[] locationList = getActivity().getResources().getStringArray(R.array.location_list);
updateEditText(locationList[position]);
listener.onInputASent(locationList[position]);
}
public interface FragmentAListener {
void onInputASent(CharSequence input);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a, container, false);
return v;
}
#Override
public void onListItemClick(#NonNull ListView l, #NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
}
public void updateEditText(CharSequence newText) {
//editText.setText(newText);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentAListener) {
listener = (FragmentAListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentAListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter arrayAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.location_list, android.R.layout.simple_list_item_1);
setListAdapter(arrayAdapter);
getListView().setOnItemClickListener(this);
}
}
FragmentB.Java - This is the fragment that needs to be keep the string inside the TextView when the screen is rotated
package com.example.tourguide;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class FragmentB extends Fragment {
private FragmentBListener listener;
private TextView resultsFrag;
private static final String KEY_TITLE = "title_key";
private String stateObject;
public interface FragmentBListener {
void onInputBSent(CharSequence input);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_b, container, false);
resultsFrag = v.findViewById(R.id.tvFragmentB);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 1", Toast.LENGTH_SHORT).show();
}
return v;
}
public void updateEditText(CharSequence newText) {
String newOption = newText.toString();
stateObject = newText.toString();
Resources res = getResources();
String[] locationDesc = res.getStringArray(R.array.location_description);
if (newOption.equals("Calgary")) {
resultsFrag.setText(locationDesc[0]);
} else if (newOption.equals("Victoria")) {
resultsFrag.setText(locationDesc[1]);
} else if (newOption.equals("Vancouver")) {
resultsFrag.setText(locationDesc[2]);
} else if (newOption.equals("Toronto")) {
resultsFrag.setText(locationDesc[3]);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentBListener) {
listener = (FragmentBListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentBListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TITLE, resultsFrag.getText().toString());
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 2", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 3", Toast.LENGTH_SHORT).show();
}
}
}
fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="#+id/tvFragmentB"
android:layout_width="match_parent"
android:layout_height="602dp" />
</LinearLayout>
Strings
<resources>
<string name="app_name">Tour Guide</string>
<string-array name="location_list">
<item>Calgary</item>
<item>Victoria</item>
<item>Vancouver</item>
<item>Toronto</item>
</string-array>
<!-- Descriptions for the locations -->
<string-array name="location_description">
<item>This is a big description for CALGARY - THIS needs to load in for more information regarding CALGARY</item>
<item>This is a big description for VICTORIA - THIS needs to load in for more information regarding VICTORIA</item>
<item>This is a big description for VANCOUVER - THIS needs to load in for more information regarding VANCOUVER</item>
<item>This is a big description for TORONTO - THIS needs to load in for more information regarding TORONTO</item>
</string-array>
</resources>
fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_green_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="206dp" />
</LinearLayout>
activity_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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/container_a"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/container_b"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
They are saved, but you are replacing them. Use this
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commit();
}
Please note that fragment instantiation is pretty much the ONLY scenario in which this check yields correct and expected results.
Do not keep a reference to a Fragment, unless it is obtained via findFragmentByTag + instantiation. You might want to use commitNow to get reliable results in this case.
EDIT: Update with more complete code:
public class MainActivity extends AppCompatActivity implements FragmentA.FragmentAListener, FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA(), "fragmentA");
ft.replace(R.id.container_b, new FragmentB(), "fragmentB");
ft.commitNow();
}
fragmentA = getSupportFragmentManager().findFragmentByTag("fragmentA");
fragmentB = getSupportFragmentManager().findFragmentByTag("fragmentB");
}
I develop (NEWS Android app) with android studio and I have a problem, I Post a Short topic in the app and I need to let the user see the full topic when clicks on TextView (Click Here), but I need to change the site link on every topic. Anyone can help me, please ??
I Update the news through (Firebase Database and Online Database)
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
public class Home extends AppCompatActivity {
RequestQueue requestQueue;
String url = "https://mobarmejlebanon.000webhostapp.com/show.php";
TextView textView;
ListView listview;
ArrayList<listitme> listitmes = new ArrayList<listitme>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
textView = (TextView) findViewById(R.id.textView);
listview = (ListView) findViewById(R.id.listview);
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("allstudents");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject respons = jsonArray.getJSONObject(i);
String id = respons.getString("id");
String name = respons.getString("name");
String info = respons.getString("info");
String img = respons.getString("img");
listitmes.add(new listitme(id, name, info, img));
listAllItme();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", "ERROR");
}
}
);
requestQueue.add(jsonObjectRequest);
}
public void listAllItme() {
listAdpter lA = new listAdpter(listitmes);
listview.setAdapter(lA);
}
class listAdpter extends BaseAdapter {
ArrayList<listitme> listA = new ArrayList<listitme>();
public listAdpter(ArrayList<listitme> listA) {
this.listA = listA;
}
#Override
public int getCount() {
return listA.size();
}
#Override
public Object getItem(int position) {
return listA.get(position).id;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = getLayoutInflater();
View view = layoutInflater.inflate(R.layout.row_item, null);
TextView id = (TextView) view.findViewById(R.id.textView_id);
TextView name = (TextView) view.findViewById(R.id.textView_name);
TextView info = (TextView) view.findViewById(R.id.textView_info);
ImageView img = (ImageView) view.findViewById(R.id.image);
id.setText(listA.get(position).id);
name.setText(listA.get(position).name);
info.setText(listA.get(position).info);
Picasso.with(Home.this).load("https://mobarmejlebanon.000webhostapp.com/images/" + listA.get(position).img).into(img);
return view;
}
}
}
Here is the Firebase database code
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class Topic2 extends AppCompatActivity {
TextView TopicTitle,Topic;
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference mRootReference = firebaseDatabase.getReference();
DatabaseReference mKidRefernece = firebaseDatabase.getReference("topictwotitle");
DatabaseReference mChildReference = mRootReference.child("topictwomessage");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic2);
TopicTitle = (TextView) findViewById(R.id.twotitle);
Topic = (TextView) findViewById(R.id.twomsg);
TopicTitle.setText("Please Wait");
Topic.setText("Loading");
}
#Override
protected void onStart() {
super.onStart();
mChildReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String message = dataSnapshot.getValue(String.class);
Topic.setText(message);
mKidRefernece.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String topictitle = dataSnapshot.getValue(String.class);
TopicTitle.setText(topictitle);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
I suggest you to use CardView and RecyclerView in order to achieve your purpose. You can get a better insight of it here:
Also you can catch a glimpse of it in action here and hither.
EDIT
According to the new query regarding this question; I think you must catch up this How to get a text after clicking on the CardView.
Happy Coding...
EDIT
Here is your sample:
I added dummy right now.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<TopicDTO> topics = new ArrayList<>();
for (int i = 0; i < 10; i++) {
topics.add(new TopicDTO("" + i, "Topic " + (i + 1), "Your Topic info goes here", "Your Topic Image goes here", "http://www.google.com"));
}
ListView listTopics = (ListView) findViewById(R.id.listTopics);
listTopics.setAdapter(new TopicsListAdapter(MainActivity.this, topics));
}
}
TopicsListAdapter.java
public class TopicsListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<TopicDTO> mData;
public TopicsListAdapter(Context context, ArrayList<TopicDTO> data) {
mInflater = LayoutInflater.from(context);
mData = data;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ChildViewHolder holder;
if (convertView == null) {
holder = new ChildViewHolder();
convertView = mInflater.inflate(R.layout.row_topics, parent,
false);
holder.textTopicTitle = (TextView) convertView
.findViewById(R.id.textTopicTitle);
holder.textTopicInfo = (TextView) convertView
.findViewById(R.id.textTopicInfo);
holder.textTopicLink = (TextView) convertView
.findViewById(R.id.textTopicLink);
convertView.setTag(holder);
} else {
holder = (ChildViewHolder) convertView.getTag();
}
final TopicDTO mItem = mData.get(position);
holder.textTopicTitle.setText(mItem.name);
holder.textTopicInfo.setText(mItem.info);
/*You need to have a more info link per topic*/
holder.textTopicLink.setClickable(true);
holder.textTopicLink.setMovementMethod(LinkMovementMethod.getInstance());
String text = "<a href='" + mItem.moreInfoLink + "'> Click here to see full topic </a>";
holder.textTopicLink.setText(Html.fromHtml(text));
return convertView;
}
class ChildViewHolder {
TextView textTopicTitle, textTopicInfo, textTopicLink;
}
}
row_topics.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textTopicTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textTopicInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp" />
</LinearLayout>
</LinearLayout>
<!--You need to add extra TextView in your row file of listview.
It will work as a link per topic.-->
<TextView
android:id="#+id/textTopicLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="Click here to see full topic" />
</LinearLayout>
Read each comment carefully and then implement it. That's it. Nothing can be better than this.
OLD
You need to have a textView for each topic you have.You have something like listview or recyclerview. Then when user clicks on that textView open link associated with that topic only that is from your dataset of listview.
Try this on your textview on which you want to open a link :
info.setClickable(true);
info.setMovementMethod(LinkMovementMethod.getInstance());
String text = "<a href='http://www.google.com'> Google </a>";
info.setText(Html.fromHtml(text));
Replace "http://www.google.com" with your topic's link.
I have created a sample app using the "Master / Detail flow" activity. I have added two buttons, Next and Prev to the detail activity. How to I set programmatically the buttons actions instead having to go back and forth between the List and detail?
item_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:weightSum="4"
android:gravity="end"
android:orientation="horizontal">
<Button
android:id="#+id/button_prev"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Prev"/>
<Button
android:id="#+id/button_next"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Next"/>
</LinearLayout>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/item_detail"
style="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:textIsSelectable="true"
tools:context="co.test.app.sample.itemapplication.ItemDetailFragment"/>
</LinearLayout>
activity_item_detail.xml
<android.support.design.widget.CoordinatorLayout 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:fitsSystemWindows="true"
tools:context="co.test.app.sample.itemapplication.ItemDetailActivity"
tools:ignore="MergeRootFrame">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<android.support.v7.widget.Toolbar
android:id="#+id/detail_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/item_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
DummyContent.java
package co.test.app.sample.itemapplication.dummy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Helper class for providing sample content for user interfaces created by
* Android template wizards.
* <p>
* TODO: Replace all uses of this class before publishing your app.
*/
public class DummyContent {
/**
* An array of sample (dummy) items.
*/
public static final List<DummyItem> ITEMS = new ArrayList<DummyItem>();
/**
* A map of sample (dummy) items, by ID.
*/
public static final Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
private static final int COUNT = 25;
static {
// Add some sample items.
for (int i = 1; i <= COUNT; i++) {
addItem(createDummyItem(i));
}
}
private static void addItem(DummyItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
private static DummyItem createDummyItem(int position) {
return new DummyItem(String.valueOf(position), "Item " + position, makeDetails(position));
}
private static String makeDetails(int position) {
StringBuilder builder = new StringBuilder();
builder.append("Details about Item: ").append(position);
for (int i = 0; i < position; i++) {
builder.append("\nMore details information here.");
}
return builder.toString();
}
/**
* A dummy item representing a piece of content.
*/
public static class DummyItem {
public final String id;
public final String content;
public final String details;
public DummyItem(String id, String content, String details) {
this.id = id;
this.content = content;
this.details = details;
}
#Override
public String toString() {
return content;
}
}
}
ItemDetailActivity.java
package co.test.app.sample.itemapplication;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
/**
* An activity representing a single Item detail screen. This
* activity is only used narrow width devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a {#link ItemListActivity}.
*/
public class ItemDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
setSupportActionBar(toolbar);
// Show the Up button in the action bar.
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don't need to manually add it.
// For more information, see the Fragments API guide at:
//
// http://developer.android.com/guide/components/fragments.html
//
if (savedInstanceState == null) {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID,
getIntent().getStringExtra(ItemDetailFragment.ARG_ITEM_ID));
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.add(R.id.item_detail_container, fragment)
.commit();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
navigateUpTo(new Intent(this, ItemListActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
ItemListActivity.java
package co.test.app.sample.itemapplication;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import co.test.app.sample.itemapplication.dummy.DummyContent;
import java.util.List;
/**
* An activity representing a list of Items. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {#link ItemDetailActivity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
*/
public class ItemListActivity extends AppCompatActivity {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
View recyclerView = findViewById(R.id.item_list);
assert recyclerView != null;
setupRecyclerView((RecyclerView) recyclerView);
if (findViewById(R.id.item_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
}
}
private void setupRecyclerView(#NonNull RecyclerView recyclerView) {
recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(DummyContent.ITEMS));
}
public class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final List<DummyContent.DummyItem> mValues;
public SimpleItemRecyclerViewAdapter(List<DummyContent.DummyItem> items) {
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list_content, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).content);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, ItemDetailActivity.class);
intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
context.startActivity(intent);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public DummyContent.DummyItem mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
}
This is the code snippet used to forward to the detail page.
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, ItemDetailActivity.class);
intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
context.startActivity(intent);
}
You can forward to any page by changing the value of arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.id);
Use the above snippets in the onClick events of next and prev buttons. cheers :)
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
I am getting a NullPointerException at line 67 while trying to set a listView with a chat adapter. Here is the class:
I have placed ** around the line I am getting the NullPointerException on. I'm not really understading why its returning as null when I'm setting messageAdapter to a new object of an inner class called ChatAdapter(this).
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MessageListActivity extends AppCompatActivity {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
ListView listView;
Button sendButton;
ArrayList<String> arrayList = new ArrayList<String>();
ChatDatabaseHelper Cdb;
private boolean mTwoPane;
ChatAdapter messageAdapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_list);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
listView = (ListView)findViewById(R.id.chatListView);
final EditText editText = (EditText)findViewById(R.id.messageText);
sendButton = (Button)findViewById(R.id.sendButton);
messageAdapter = new ChatAdapter(this); // chatAdapter is a built in adapater
**listView.setAdapter(messageAdapter);**
Cdb = new ChatDatabaseHelper(this);
Cursor cursor = Cdb.getMessages(); // get messages method is of type Cursor from database helper class
// cursor will move through the database to find the next text if there is any.
while (cursor.moveToNext()) { arrayList.add(cursor.getString(cursor.getColumnIndex(Cdb.KEY_MESSAGE))); }
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { // on click listener for the send button
String chatText = editText.getText().toString(); // changing editText to String
arrayList.add(chatText); // adding the string from EditTest to arrayList
boolean isInserted = Cdb.insertData(chatText); // inserting the message text into the database
if(isInserted = true)
{ Toast.makeText(MessageListActivity.this,"Message Sent",Toast.LENGTH_SHORT).show(); } // if the message inserts into the database this toast will show
else {
Toast.makeText(MessageListActivity.this,"Message not Sent",Toast.LENGTH_SHORT).show(); } // if message does not nter the database this toast will show
messageAdapter.notifyDataSetChanged(); // notifying the adapter that a message has been sent, changing from incoming to outgoing
editText.setText(" "); // set the text on the send button to blank.
} // end of onClick view
}); // end of onClickListener
if (findViewById(R.id.message_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
}
}
class ChatAdapter extends ArrayAdapter<String> { // custom adapter class // when youc all the adapter it forms the for loop for you.
public ChatAdapter(MessageListActivity ctx) {
super(ctx, 0);
} // default constructor
// method to return the number of rows that will be in your array
// will tell how many times to run a for loop
public int getCount(){ return arrayList.size(); } // will return the size of the array
public String getItem(int position){ return arrayList.get(position); } // will return the item at position
// getview method
#Override
public View getView(int position, final View convertView, ViewGroup parent) {// inner class
LayoutInflater Inflater = MessageListActivity.this.getLayoutInflater(); // an inflater inflates the xml layout into a view.
View result = null;
if(position%2 == 0){ // if position number in the array is odd do this, if number is even, do this.
result = Inflater.inflate(R.layout.chat_row_incoming, null); // depending on the position, show layout incoming
} else {
result = Inflater.inflate(R.layout.chat_row_outgoing,null); // depending on the position, show layout outgoing
}
TextView message = (TextView)result.findViewById(R.id.messageText); // creating a message of type TextView connected to messageText
final String messageText = getItem(position) ;
message.setText(messageText);
result.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(MessageDetailFragment.ARG_ITEM_ID,messageText );
MessageDetailFragment fragment = new MessageDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.message_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, MessageDetailActivity.class);
intent.putExtra(MessageDetailFragment.ARG_ITEM_ID,messageText );
context.startActivity(intent);
}
}
});
return result; // return the view which is the Inflater.
}
} // end of chat adapter class
private void setupRecyclerView(#NonNull RecyclerView recyclerView) {
recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(DummyContent.ITEMS));
}
public class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final List<DummyContent.DummyItem> mValues;
public SimpleItemRecyclerViewAdapter(List<DummyContent.DummyItem> items) {
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.message_list_content, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).content);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(MessageDetailFragment.ARG_ITEM_ID, holder.mItem.id);
MessageDetailFragment fragment = new MessageDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.message_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, MessageDetailActivity.class);
intent.putExtra(MessageDetailFragment.ARG_ITEM_ID, holder.mItem.id);
context.startActivity(intent);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public DummyContent.DummyItem mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
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.example.ChatWindow">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/chatListView"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="false"
android:layout_alignWithParentIfMissing="false"
android:layout_above="#+id/sendButton" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sendButton"
android:id="#+id/sendButton"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:singleLine="true" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/messageText"
android:layout_toStartOf="#id/sendButton"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:enabled="true"
/>
</RelativeLayout>
just try
messageAdapter = new ChatAdapter(MessageListActivity .this);