I am trying to learn building Android apps. I am reading the book "Android 5 Programming by Example" and trying sample codes from there. However I have problem with "CardView with Layout" chapter. First, I can not arrange my pictures and text like samples in the book, especially in landscape view - i can't move text to the right of the picture. Second thing is, I have an exception when I click on the images. Problem is in DetailActivity.class file and line "detailText.setMovementMethod (new ScrollingMovementMethod());". I get these errors:
FATAL EXCEPTION: main Process: com.example.rado.ancientbritain, PID: 10017 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.rado.ancientbritain/com.example.rado.ancientbritain.DetailActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setMovementMethod(android.text.method.MovementMethod)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setMovementMethod(android.text.method.MovementMethod)' on a null object reference at com.example.rado.ancientbritain.DetailActivity.onCreate(DetailActivity.java:30) at android.app.Activity.performCreate(Activity.java:5990) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
My files:
1. DetailActivity
package com.example.rado.ancientbritain;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
public class DetailActivity extends AppCompatActivity {
private ImageView detailImage;
private ArrayList<MainDataDef> detailData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
detailImage = (ImageView) findViewById(R.id.detail_image);
TextView detailName = (TextView) findViewById(R.id.detail_name);
TextView detailDistance = (TextView) findViewById(R.id.detail_distance);
TextView detailText = (TextView) findViewById(R.id.detail_text);
detailText.setMovementMethod (new ScrollingMovementMethod());
ImageView detailWebLink = (ImageView) findViewById(R.id.detail_web_link);
setContentView(R.layout.activity_detail);
int i = MainActivity.currentItem;
Random n = new Random();
int m = n.nextInt((600 - 20) + 1) + 20;
setTitle(getString(R.string.app_name) + " - " + MainData.
nameArray[i]);
detailImage.setImageResource(MainData.detailImageArray[i]);
detailName.setText(MainData.nameArray[i]);
detailDistance.setText(String.valueOf(m) + " miles");
detailText.setText(MainData.detailTextArray[i]);
detailWebLink.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(
MainData.detailWebLink[MainActivity.currentItem]));
startActivity(intent);
}
});
}
}
MainActivity
package com.example.rado.ancientbritain; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; public static int currentItem; static View.OnClickListener mainOnClickListener; private class MainOnClickListener implements View.OnClickListener { private final Context context; private MainOnClickListener(Context c) { this.context = c; } @Override public void onClick(View v) { currentItem = recyclerView.getChildAdapterPosition(v); startActivity(new Intent(getApplicationContext(), DetailActivity.class)); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.main_recycler_view); recyclerView.setHasFixedSize(true); mainOnClickListener = new MainOnClickListener(this); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); ArrayList<MainDataDef> mainData = new ArrayList<MainDataDef>(); for (int i = 0; i < MainData.nameArray.length; i++) { mainData.add(new MainDataDef( MainData.imageArray[i], MainData.nameArray[i], MainData.infoArray[i] )); } RecyclerView.Adapter adapter = new MainAdapter(mainData); recyclerView.setAdapter(adapter); } }
MainAdapter
package com.example.rado.ancientbritain; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; /** * Created by Rado on 7.9.2017 г.. */ public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainViewHolder> { private ArrayList<MainDataDef> mainData; public MainAdapter(ArrayList<MainDataDef> a) { this.mainData = a; } @Override public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.card_main, parent, false); v.setOnClickListener(MainActivity.mainOnClickListener); return new MainViewHolder(v); } @Override public void onBindViewHolder(final MainViewHolder holder, final int position) { ImageView imageIcon = holder.imageIcon; TextView textName = holder.textName; TextView textInfo = holder.textInfo; imageIcon.setImageResource(mainData.get(position).getImage()); textName.setText(mainData.get(position).getName()); textInfo.setText(mainData.get(position).getInfo()); } @Override public int getItemCount() { return mainData.size(); } public static class MainViewHolder extends RecyclerView.ViewHolder { ImageView imageIcon; TextView textName; TextView textInfo; public MainViewHolder(View v) { super(v); this.imageIcon = (ImageView) v.findViewById(R.id.card_image); this.textName = (TextView) v.findViewById(R.id.card_name); this.textInfo = (TextView) v.findViewById(R.id.card_info); } } }
MainData
package com.example.rado.ancientbritain; /** * Created by Rado on 7.9.2017 г.. */ public class MainData { static Integer[] imageArray = {R.drawable.henge_icon, R.drawable.horse_icon, R.drawable.wall_icon, R.drawable.skara_brae_icon, R.drawable.tower_icon}; static String[] nameArray = {"Stonehenge", "Uffington White Horse", "Hadrian's wall", "Skara Brae", "Tower of London"}; static String[] infoArray = {"Aylsbury, Wiltshire", "Uffington, Oxfordshire", "Cumbria - Durham", "Mainland, Orkney", "Tower Hamlets, London"}; static Integer[] detailImageArray = {R.drawable.henge_large, R.drawable.horse_large, R.drawable.wall_large, R.drawable.skara_brae_large, R.drawable.tower_large}; static Integer[] detailTextArray = {R.string.detail_text_henge, R.string.detail_text_horse, R.string.detail_text_wall, R.string.detail_text_skara, R.string.detail_text_tower}; static String[] detailWebLink = {"https://en.wikipedia.org/wiki/Stonehenge", "https://en.wikipedia.org/wiki/Uffington_White_Horse", "https://en.wikipedia.org/wiki/Hadrian%27s_Wall", "https://en.wikipedia.org/wiki/Skara_Brae", "https://en.wikipedia.org/wiki/Tower_of_London"}; }
MainDataDef
package com.example.rado.ancientbritain; /** * Created by Rado on 7.9.2017 г.. */ public class MainDataDef { int image; String name; String info; public MainDataDef(int image, String name, String info) { this.image = image; this.name = name; this.info = info; } public int getImage() { return image; } public String getName() { return name; } public String getInfo() { return info; } }
Layout 1. activty_detail.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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/detail_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_weight="3"
app:srcCompat="@drawable/wall_large" />
<TextView
android:id="@+id/detail_name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Name" />
<TextView
android:id="@+id/detail_distance"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Distance" />
<TextView
android:id="@+id/detail_text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:layout_weight="2"
android:textAppearance="?android:attr/textAppearanceSmall"
android:maxLines = "100"
android:scrollbars = "vertical"
android:text="Text" />
<ImageView
android:id="@+id/detail_web_link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
app:srcCompat="@drawable/web_icon" />
</LinearLayout>
activity_main.xml
<android.support.v7.widget.RecyclerView android:id="@+id/main_recycler_view" android:layout_width="368dp" android:layout_height="495dp" tools:layout_editor_absoluteY="8dp" tools:layout_editor_absoluteX="8dp" /> />
card_main.xml
<android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="100dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/card_image" android:layout_width="0dp" android:layout_weight="2" app:srcCompat="@mipmap/ic_launcher" android:contentDescription="" android:layout_height="match_parent" /> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="5" android:orientation="vertical"> <TextView android:id="@+id/card_name" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="card_name" /> <TextView android:id="@+id/card_info" android:textAppearance="?android:attr/textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="card_info" /> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>
Layout-landscape activity_detail.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:orientation="vertical"
android:layout_width="match_parent"
android:layout_weight="3"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/detail_image"
android:layout_width="286dp"
android:layout_height="213dp"
android:layout_weight="0.5"
android:layout_gravity="center_vertical"
app:srcCompat="@drawable/wall_large" />
<TextView
android:id="@+id/detail_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/detail_distance"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars = "vertical"
android:gravity="center"
android:text="Distance" />
<TextView
android:id="@+id/detail_text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:layout_gravity="left"
android:layout_marginLeft="8dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:maxLines = "100"
android:scrollbars = "vertical"
android:text="Text" />
<ImageView
android:id="@+id/detail_web_link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
app:srcCompat="@drawable/web_icon" />
</LinearLayout>
and build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.example.rado.ancientbritain"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:cardview-v7:26.0.+'
compile 'com.android.support:recyclerview-v7:26.0.+'
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}