I am new to Java and Android, so please have mercy. I have 3 buttons and imageView in my activity. Each button generates new version of the picture displayed in ImageView. I would like the imageView to enlarge the current picture to full screen when I click on it. My question is: What would be the best approach to achieve this?
Should I create onClickListener to enlarge the picture?
Should I define a method for ImageView to call in activity_start.xml like android:onClick="myMethodToCall
My activity_start.xml code:
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:onClick="template1match"
android:text="image1" />
<Button
android:id="#+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/button1"
android:layout_centerHorizontal="true"
android:onClick="template2match"
android:text="image2" />
<Button
android:id="#+id/button3"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/button2"
android:layout_marginRight="16dp"
android:onClick="template3match"
android:text="image3" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:clickable="true"
android:src="#drawable/wall" />
My Start.java code:
package com.example.matchtemplate;
import java.io.File;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class Start extends Activity {
Button button1;
Button button2;
Button button3;
ImageView imageView1;
File cacheDir;
protected static final String TAG = "OpenCV";
private BaseLoaderCallback mLoaderCallBack = new BaseLoaderCallback(this) {
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
Log.i(TAG, "Open CV loaded successfully");
break;
default:
super.onManagerConnected(status);
break;
}
};
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
//addListenerOnButton();
initDir();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.start, menu);
return true;
}
#Override
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this,
mLoaderCallBack);
}
// ADDED THIS: to create/initialize external file
// Be sure write permissions is enabled in the manifest file
// ie add: <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE"/>
public void initDir() {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
cacheDir = new File(
android.os.Environment.getExternalStorageDirectory(),
"FileList");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
}
}
// added this to simplify creating full file path
public String getFileAbsPath(String fileName) {
File f = new File(cacheDir, fileName);
return f.getAbsolutePath();
}
public void template1match(View v) {
imageView1 = (ImageView) findViewById(R.id.imageView1);
button1 = (Button) findViewById(R.id.button1);
String infile = getFileAbsPath("wall.jpg");
String tp = getFileAbsPath("template1.jpg");
String outFile = getFileAbsPath("result.jpg");
try {
matchTemplate(infile, tp, outFile, Imgproc.TM_CCOEFF);
Bitmap bm = BitmapFactory.decodeFile(outFile);
imageView1.setImageBitmap(bm);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void template2match(View v) {
imageView1 = (ImageView) findViewById(R.id.imageView1);
button2 = (Button) findViewById(R.id.button2);
String infile = getFileAbsPath("wall.jpg");
String tp = getFileAbsPath("template2.jpg");
String outFile = getFileAbsPath("result.jpg");
try {
matchTemplate(infile, tp, outFile, Imgproc.TM_CCOEFF);
Bitmap bm = BitmapFactory.decodeFile(outFile);
imageView1.setImageBitmap(bm);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void template3match(View v) {
imageView1 = (ImageView) findViewById(R.id.imageView1);
button3 = (Button) findViewById(R.id.button3);
String infile = getFileAbsPath("wall.jpg");
String tp = getFileAbsPath("template3.jpg");
String outFile = getFileAbsPath("result.jpg");
try {
matchTemplate(infile, tp, outFile, Imgproc.TM_CCOEFF);
Bitmap bm = BitmapFactory.decodeFile(outFile);
imageView1.setImageBitmap(bm);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void matchTemplate(String inFile, String templateFile,
String outFile, int match_method) {
Log.i(TAG, "Running Template Matching");
Mat img = Highgui.imread(inFile);
Mat templ = Highgui.imread(templateFile);
// / Create the result matrix
int result_cols = img.cols() - templ.cols() + 1;
int result_rows = img.rows() - templ.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// / Do the Matching and Normalize
Imgproc.matchTemplate(img, templ, result, match_method);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
// / Localizing the best match with minMaxLoc
MinMaxLocResult mmr = Core.minMaxLoc(result);
Point matchLoc;
if (match_method == Imgproc.TM_SQDIFF
|| match_method == Imgproc.TM_SQDIFF_NORMED) {
matchLoc = mmr.minLoc;
} else {
matchLoc = mmr.maxLoc;
}
// / Show me what you got
Core.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
matchLoc.y + templ.rows()), new Scalar(0, 255, 0));
// Save the visualized detection.
Log.i(TAG, "Writing: " + outFile);
Highgui.imwrite(outFile, img);
}
}
The two are equivalent- all that happens with the xml is that behind the scenes Android will create an onClickListener for you, register it, and that listener will call the function named in the xml. So there's no real reason to prefer one over the other. Since there's no reason to care, I tend to go the xml route as it requires slightly less code.
i saw the Gabe's answer.But i will have my own answer.Both are same despite in case of xml Android will take care of creating the onClicListener for you.But i will prefer to go for coding rather than xml as it will be easier to understand.Suppose someone will see your code tomorrow and will click the image and image will enlarge, he will not the onClicklistener in the code so may get confuse at his first look.Though if he will be a good coder he will look for xml,but if it will be there in the code itself then it will be easier to understand.
if I was in your place I would implement an alert dialogue once the image is clicked, and in the alert dialogue there is a custom .xml which has a fill_parent imageview. So once the image is clicked the alert comes and the image inside becomes the image clicked
Related
I am trying to create an asset manager for android that will open text from a text file and and image. However, when I try to run it, it says it has stopped working. Using the LogCat, this is the error I can find that I think may be causing the issue:
java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.view.ViewGroup
Here is the code for the main activity:
package AssetDemo.eoghanalphagame;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Asset_Activity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Define the type of activity we want created - no title, full screen
// and keep the screen on whilst it is visible. This needs to be
// completed before any components
// are inflated.
Window window = getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Set the content view up to hold a single fragment
setContentView(R.layout.fragment_asset_);
// Add whatever fragment is appropriate for the derived call - calling
// the overloaded createFragment() method to retrieve the fragment.
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_asset_ImageView);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction().add(R.id.fragment_asset_ImageView, fragment)
.commit();
}
}
/**
* Get the fragment for this particular activity
*
* #return Fragment for this activity
*/
public Fragment createFragment(){
return new AssetTestFragment();
}
}
Here is the code for the fragment:
package AssetDemo.eoghanalphagame;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Fragment;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class AssetTestFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
//inflate the view
View view = inflater.inflate(R.layout.fragment_asset_, container, false);
//get assest manager for current activity and load in text and image
AssetManager assetManager = getActivity().getAssets();
String text = loadText(assetManager, "Text/test.txt");
Bitmap bitmap = loadBitmap(assetManager, "Images/TheVanishingOfEthanCarter_logo_t.png");
//Display the text
TextView outputTextView = (TextView) view.findViewById(R.id.fragment_asset_TextView);
outputTextView.setText(text != null ? text: "ERROR: Could not open text file.");
//Display the bitmap
ImageView imageView = (ImageView) view.findViewById(R.id.fragment_asset_ImageView);
if(bitmap != null)
{
imageView.setImageBitmap(bitmap);
}
return view;
}
//Create the loadText method
private String loadText(AssetManager assetManager, String asset)
{
String text = null;
InputStream inputStream = null;
try
{
//Try to open text file
inputStream = assetManager.open(asset);
//Load in Text in 4k chunks
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] chunk = new byte[4096];
int len = 0;
while((len = inputStream.read(chunk)) > 0)
byteStream.write(chunk, 0, len);
//convert and return as a UFT8 String
text = new String(byteStream.toByteArray(), "UTF8");
}catch (IOException e)
{
Log.e(getActivity().getResources().getString(R.string.LOG_TAG),
"Error loading text asset: " + e.getMessage());
} finally
{
if(inputStream != null)
try
{
inputStream.close();
} catch (IOException e)
{/*returns a null}*/
}
}
return text;
}
//Load the Bitmap
private Bitmap loadBitmap(AssetManager assetManager, String asset)
{
Bitmap bitmap = null;
InputStream inputStream = null;
try
{
//Try to open the bitmap
inputStream = assetManager.open(asset);
//Setup load prefrences
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//Load the Bitmap
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
} catch (IOException e)
{
Log.e(getActivity().getResources().getString(R.string.LOG_TAG),
"Error Loading Bitmap: " +e.getMessage());
} finally
{
if(inputStream != null)
try
{
inputStream.close();
} catch (IOException e)
{/*returns a null*/
}
}
return bitmap;
}
}
And here is the XML file that the TextView and ImageView are created in:
<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="AssetDemo.eoghanalphagame.Asset_Activity$PlaceholderFragment" >
<ImageView
android:id="#+id/fragment_asset_ImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/fragment_asset_TextView"
android:layout_below="#+id/fragment_asset_TextView"
android:layout_marginTop="28dp"
android:contentDescription="#string/desc" />
<TextView
android:id="#+id/fragment_asset_TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="16dp"
android:text="#string/hello_world" />
</RelativeLayout>
What I want to know is why it is not working and what needs to be changed to make it work. I have created all the files I have referenced. I feel like it is something simple I am missing, but being new to android development I have no idea what.
Thanks
Sometimes a build after a "clean" will make things OK.
Because if you change the view's ID , the mentioned Exception may come.
I have an existing application that I am trying to modify and could really use some help.
It is a chat application. The original flow of the application was as follows:
Launch-> Splash Screen Activity-> MainActivity (extending Actionbar Sherlock)
Once in the main activity the default fragment is the ChatRoomFragment. From there you can select different tabs and interact with the application.
What I would like to change about the flow to is the following:
Launch->Splash Screen Activity-> Terms of Service/Sign -> MainMenu->MainActivity
I have created the mainmenu layout to contain 4 buttons. Join, Search, Profile, Settings
Here is the problem. My Join button works fine, onClick simply triggers the intent to start MainActivity and and the chat room loads. From this screen you can access the different tabs and fragments within the application.
However, I now would like to have the "search" button set to open a dialog. With a editText field and a search button. Upon clicking search it should pass the search string to the PlacesSearchFragment and populate results.
I copied the code from within my application where this search is normally completed (inside the ChatRoomsFragment but it will not work from within my mainMenu Activity.
How do I start the new fragment from the menu activity??
Code Below:
menuActivity.java
package com.peekatucorp.peekatu;
//import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class menuActivity extends Activity implements ActionBar.TabListener {
Button b1;
Button b2;
Button b3;
EditText txtsearch;
final private static int DIALOG_LOGIN = 1;
final private static int DIALOG_FORGET = 2;
final private static int DIALOG_SEARCH = 3;
private android.app.FragmentTransaction ft;
#Override
public void onCreate(Bundle savedInstanceState) {
SharedPreferences preferences = this.getSharedPreferences("MyPreferences", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu);
if(preferences.getString("Username", "").length()<=0 || preferences.getString("loggedin_user", "").length()<=0){
showDialog(DIALOG_LOGIN);
}
b1= (Button) this.findViewById(R.id.joinbutton);
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(menuActivity.this, MainActivity.class);
menuActivity.this.startActivity(intent);
SharedPreferences preferences = getSharedPreferences("MyPreferences", MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("loadMain", "1");
editor.commit();
}
});
b2= (Button) this.findViewById(R.id.searchbutton);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
showDialog(DIALOG_SEARCH);
}
}
);
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog dialogDetails = null;
switch (id) {
case DIALOG_LOGIN:
if(true){
....some code}
break;
case DIALOG_FORGET:
if(true){
...some code
}
break;
case DIALOG_SEARCH:
if(true){
LayoutInflater inflater = LayoutInflater.from(this);
View dialogview = inflater.inflate(R.layout.menusearch_layout, null);
AlertDialog.Builder dialogbuilder = new AlertDialog.Builder(this);
dialogbuilder.setTitle("Where ya headed?");
dialogbuilder.setView(dialogview);
dialogDetails = dialogbuilder.create();
}
}
return dialogDetails;
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
switch (id) {
case DIALOG_LOGIN:
...some code
break;
case DIALOG_SEARCH:
final AlertDialog alertDialog3 = (AlertDialog) dialog;
final Button btnLocalsearch = (Button) alertDialog3
.findViewById(R.id.local_search);
final Button btnSearch = (Button) alertDialog3
.findViewById(R.id.btn_search);
final EditText txtsearch = (EditText) alertDialog3
.findViewById(R.id.txtsearch);
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
//showDialog(DIALOG_FORGET);
//alertDialog3.dismiss();
// TODO Auto-generated method stub
menuActivity m = com.peekatucorp.peekatu.menuActivity.this;
final TabInfo tab = com.peekatucorp.peekatu.menuActivity.this.getCurrentTabInfo();
final PlacesSearchFragment fragment = new PlacesSearchFragment().setNAV(m).setSearch(txtsearch.getText().toString(),"1");
// fragment.setText(characters[position]);
// second, you push the fragment. It becomes visible and the up button is
// shown
m.pushFragment(tab, fragment);
}
});
}
mainmenu.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:layout_width="wrap_content"
android:layout_height="65dp"
android:layout_marginLeft="10dip"
android:src="#drawable/registration_banner3"
android:id="#+id/imageView" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Chat"
android:id="#+id/joinbutton"
android:layout_below="#+id/imageView"
android:layout_alignLeft="#+id/imageView"
android:layout_alignStart="#+id/imageView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"
android:id="#+id/searchbutton"
android:layout_below="#+id/joinbutton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="55dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Profile"
android:id="#+id/prfbutton"
android:layout_below="#+id/searchbutton"
android:layout_marginTop="72dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignLeft="#+id/searchbutton"
android:layout_alignStart="#+id/searchbutton" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Settings"
android:id="#+id/settingsbutton"
android:layout_below="#+id/prfbutton"
android:layout_marginTop="51dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<LinearLayout android:id="#+id/footer"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#layout/footer_repeat"
android:layout_alignParentBottom="true">
</LinearLayout>
</RelativeLayout>
ChatRoomsFragment.java (WORKING FRAGMENT)
public class ChatRoomsFragment extends SherlockFragment implements OnItemSelectedListener{
String[] items;
List<String> list;
Spinner my_spin;
RadioButton mainRoom;
RadioButton customRoom;
RadioButton GPSRoom;
EditText privateRoom;
EditText GPSsearch;
TextView GPSaddress;
String selected_public;
Context contexxt;
ImageLoader imageLoader;
public AbstractTabStackNavigationActivity navact;
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
setRetainInstance(true);
final View v = inflater.inflate(R.layout.chatrooms_layout, container, false);
contexxt = v.getContext();
// setRetainInstance(true);
SharedPreferences preferences = v.getContext().getSharedPreferences("MyPreferences", this.getActivity().MODE_PRIVATE);
my_spin=(Spinner)v.findViewById(R.id.spinner1);
my_spin.setOnItemSelectedListener(this);
selected_public = preferences.getString("selected_room", "Adult Lobby");
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
GPSsearch = (EditText)v.findViewById(R.id.cr_gps_search);
GPSaddress = (TextView)v.findViewById(R.id.cr_gps_address);
GPSaddress.setText(preferences.getString("user_location", ""));
Button search_go = (Button)v.findViewById(R.id.cr_go_search);
Button address_go = (Button)v.findViewById(R.id.cr_go_address);
Button changeroom = (Button)v.findViewById(R.id.cr_changeroom);
//Button changeroom2 = (Button)v.findViewById(R.id.cr_changeRoom2);
search_go.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
MainActivity m = (MainActivity)getActivity();
final TabInfo tab = m.getCurrentTabInfo();
final PlacesSearchFragment fragment = new PlacesSearchFragment().setNAV(m).setSearch(GPSsearch.getText().toString(),"1");
// fragment.setText(characters[position]);
// second, you push the fragment. It becomes visible and the up button is
// shown
m.pushFragment(tab, fragment);
}
});
Can someone please explain to me how to get it to load the fragment. Thank you. Let me know if I am leaving out any relevant code. Im getting a null pointer exception as my error.
Well, first of all, here is the code I was talking about in my comment:
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
menuActivity m = dialog.getOwningActivity();
final TabInfo tab = m.getCurrentTabInfo();
final PlacesSearchFragment fragment = new PlacesSearchFragment().setNAV(m).setSearch(txtsearch.getText().toString(),"1");
m.pushFragment(tab, fragment);
...
However, now that I type this up, it doesn't make sense that the NPE was on the call to pushFragment like you said. If the activity outer-class reference was really the null pointer, then it should have crashed a few lines earlier, calling getCurrentTabInfo. Thus I don't think this code change will help. Please take a second look at the stack you are seeing, and tell me what line the NPE is happening on.
So i have a simple app, just a menu with a few buttons, when a button is clicked you are brought to a new page. The page has a button, which when clicked, keeps changing its background image until it runs out of images (list of image names stored in strings), then you are brought back to the main menu. I can do this twice, then on the third attempt, if i click a button on the menu the app crashes. This doesnt happen on the emulator, only when i run it on my phone. I dont know why this is happening
package com.example.otapp;
import com.example.otapp.R.raw;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.media.MediaPlayer;
public class MainActivity extends ActionBarActivity {
public static String DPExtension;//Holds the letters dp
public String list;
public static int Screen_Height;//holds screen height
public static int Screen_Width;//holds screen width
public Intent intent;
public MediaPlayer audio;
public final static String EXTRA_MESSAGE = "com.example.otapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//this code block is for getting the screen proportions
Display getdisplay = getWindowManager().getDefaultDisplay();
DisplayMetrics dispMetrics = new DisplayMetrics();
getdisplay.getMetrics(dispMetrics);
float densitydp = getResources().getDisplayMetrics().density;
float ScreenHeightdp = dispMetrics.heightPixels / densitydp;
float ScreenWidthdp = dispMetrics.widthPixels / densitydp;
//Below dimension value holders do not use pixel density
float ScreenHeightCheck = dispMetrics.heightPixels;
float ScreenWidthCheck = dispMetrics.heightPixels;
DPExtension = "dp";
Screen_Height = (int) ScreenHeightCheck;
Screen_Width = (int) ScreenWidthCheck;
//The printlns are so I can discern the outputs in LogCat
//System.out.println("Screen Height:" + Screen_Height);
//System.out.println("Screen Width:" + Screen_Width);
View Button1 = findViewById(R.id.Button01);
LinearLayout.LayoutParams params = (LayoutParams) Button1.getLayoutParams();
params.height = Screen_Height/3;
Button1.setLayoutParams(params);
View Button2 = findViewById(R.id.Button02);
Button2.setLayoutParams(params);
View Button3 = findViewById(R.id.Button03);
Button3.setLayoutParams(params);
View Button4 = findViewById(R.id.Button04);
Button4.setLayoutParams(params);
Button1.setOnClickListener(onClickListener);
Button2.setOnClickListener(onClickListener);
Button3.setOnClickListener(onClickListener);
Button4.setOnClickListener(onClickListener);
Button1.setBackgroundResource(getResources().getIdentifier("gettingup", "drawable", getPackageName()));
intent = new Intent(this, DisplayMessageActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
audio = MediaPlayer.create(MainActivity.this, raw.buttonsound);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private OnClickListener onClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
// play sound
audio.start();
// do different things for each different button
switch(v.getId()) {
case R.id.Button01:
list = "Get Up";
intent.putExtra(EXTRA_MESSAGE, list);
startActivity(intent);
break;
case R.id.Button02:
list = "Get Dressed";
intent.putExtra(EXTRA_MESSAGE, list);
startActivity(intent);
break;
case R.id.Button03:
list = "Get Dressed";
intent.putExtra(EXTRA_MESSAGE, list);
startActivity(intent);
break;
case R.id.Button04:
list = "Get Dressed";
intent.putExtra(EXTRA_MESSAGE, list);
startActivity(intent);
break;
}
}
};
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" android:background="#1E90FF">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="#+id/Button01"
android:layout_width="match_parent"
android:layout_height="125dp"
android:text="#string/button_send"/>
<Button
android:id="#+id/Button03"
android:layout_width="match_parent"
android:layout_height="125dp"
android:text="#string/button2_send" />
<Button
android:id="#+id/Button04"
android:layout_width="match_parent"
android:layout_height="125dp"
android:text="#string/button3_send" />
<Button
android:id="#+id/Button02"
android:layout_width="match_parent"
android:layout_height="125dp"
android:text="#string/button4_send" />
</LinearLayout>
</ScrollView>
If the source above is formatted correctly, line 99, which is where the NullPointerException is thrown, is:
audio.start();
This means that audio is null. It is declared on line 83:
audio = MediaPlayer.create(MainActivity.this, raw.buttonsound);
Most likely what's happening is that the MediaPlayer.create is unable to located the raw.buttonsound. I'd debug at this line and verify that the MediaPlayer is failing to create the audio.
Try moving the definition of the onClickListener object into the onCreate method.
You can declare it as a member variable, but you should create the object and assign it to the field in onCreate()
I am testing drawing audio frequency into canvas using canvas.drawLine() method. I am able to do static draw into canvas. Basically I have a test app which has two buttons START and STOP and a Canvas where i am trying to draw the audio frequencies obtained from FFT. When i hit the START button it starts recording sound using AudioRecord class and collects data into buffer which i run through FFT to get the frequencies. This is in very early stage. Right now i am only trying to figure out how to pass these frequency values to onDraw method of my Custom View class. Here are the relevent codes starting from the layout.
activity_main.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=".MainActivity" >
<com.example.testapp.WaveForm
android:id="#+id/waveForm1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="78dp" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button1"
android:layout_alignBottom="#+id/button1"
android:layout_alignRight="#+id/waveForm1"
android:layout_marginRight="19dp"
android:text="STOP" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/waveForm1"
android:layout_alignParentTop="true"
android:text="START" />
</RelativeLayout>
I think its very starighforward. Here is my Custom View class
WaveForm.java
package com.example.testapp;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class WaveForm extends View {
private Paint mLinePaint;
float x ;
float y;
public WaveForm(Context context, AttributeSet attrs) {
super(context, attrs);
mLinePaint = new Paint();
mLinePaint.setStyle(Paint.Style.STROKE);
mLinePaint.setARGB(255, 0, 0, 255);
mLinePaint.setAntiAlias(true);
mLinePaint.setStrokeWidth(10);
x = 0.0f;
y = 0.0f;
}
#Override
protected void onDraw(Canvas canvas) {
//Instead of 50 here i would like to pass the value obtained from the Activity class
canvas.drawLine(x, 0, y, 50, mLinePaint);
y = y + 1.0f;
x = x + 1.0f;
super.onDraw(canvas);
}
}
As i mentioned in the comment in the onDraw method, i would like to pass the frequency value i obtained in the Activity instead of 50.
Finally here is my Activity:
MainActivity.java
package com.example.testapp;
import android.app.Activity;
import android.graphics.Canvas;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
boolean recording = false;
AudioRecord audioRecord;
double[] x;
double[] y;
double currentPoint = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View myInstance = (View) findViewById(R.id.waveForm1);
Button start = (Button) findViewById(R.id.button1);
start.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
int sampleRateInHz=44100;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(AudioSource.MIC, sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT, AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT));
byte[] audioData = new byte[bufferSizeInBytes/4];
FFT myFFT = new FFT(audioData.length);
Canvas canvas = new Canvas();
recording = true;
audioRecord.startRecording();
while(recording) {
audioRecord.read(audioData,0, bufferSizeInBytes/4);
//convert to double here
for(int i=0; i<audioData.length; i++) {
x[i] = (double)audioData[i];
y[i] = 0;
}
double[] samples = myFFT.fft(x, y);
for(int i=0; i<samples.length; i++) {
currentPoint = samples[i];
myInstance.draw(canvas);
myInstance.invalidate();
}
}
}
});
Button stop = (Button) findViewById(R.id.button2);
stop.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
recording = false;
audioRecord.stop();
}
});
}
}
The currentPoint variable is what i am trying to pass to the onDraw method. Thanks in advance for taking a look.
Create Getter/Setter for currentPoint variable inside WaveForm to get value from MainActivity before calling draw as:
public class WaveForm extends View {
private double currentPoint = 50;
public void setCurrentPoint(double currentPoint){
this.currentPoint=currentPoint;
}
public double getCurrentPoint(){
return this.currentPoint;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawLine(x, 0, y, getCurrentPoint(), mLinePaint);
...
}
}
and from MainActivity set currentPoint value by calling setCurrentPoint method before calling onDraw:
for(int i=0; i<samples.length; i++) {
currentPoint = samples[i];
myInstance.setCurrentPoint(currentPoint);
myInstance.draw(canvas);
myInstance.invalidate();
}
Specify currentPoint as a static variable, and use MainActivity.currentPoint to get the value of the variable from your other class. Alternatively, just use a getter method that returns the variable.
I have a basic android app set up with a scroll view and text added to it dynamically.
I want it to scroll to the bottom when text is added (which already happens) but I only want it to scroll to the bottom if you are already at the bottom, so if you're reading something it doesn't just scroll.
Here's what I have so far.
private void AddText(final String msg){
this.runOnUiThread(new Runnable() {
public void run() {
TextView log = (TextView) findViewById(R.id.chatlog);
if(log.getText().equals("Loading...")){
log.setText(msg);
}else{
ScrollView scroller = (ScrollView) findViewById(R.id.scroll_container);
//set current scroll position
int scroll_pos = scroller.getScrollY();
//scroll to bottom
scroller.fullScroll(ScrollView.FOCUS_DOWN);
//set bottom position
int scroll_bot = scroller.getScrollY();
//add the text
log.append("\r\n" + msg);
//if you weren't at the bottom
//scroll back to where you were.
//This isn't working, scroll bot is the same
//as scroll pos.
if(scroll_pos != scroll_bot){
scroller.scrollTo(0, scroll_pos);
}
//System.out.println("Pos: " + scroll_pos);
//System.out.println("Bot: " + scroll_bot);
}
}
});
}
The best solution I found so far is to use scrollView.post() method with a runnable that will be invoked after text change:
final ScrollView scrollView = (ScrollView) findViewById(R.id.consoleTab);
TextView textView = (TextView) findViewById(R.id.consoleView);
boolean autoScroll = (textView.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())) <= 0;
textView.setText(state.getConsole().getText());
if (autoScroll) {
scrollView.post(new Runnable() {
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
Here is a working example I got running in the emulator and on my galaxy s.
Basically there are two buttons to add text to the bottom text view, depending on your devices size only the second of these should be usable to see the autoscrolling. The textview being edited uses the ontextchangedlistener to check the scroll position before its text is changed and then to call a delayed (so the screen can update with the additional text) autoscroll where appropriate, after the text has changed.
The layout xml is as follows:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/scrollmain">
<RelativeLayout
android:id="#+id/mainRelative"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Welcome to the scrolling test application!" />
<Button
android:id="#+id/firstTextAddButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/titleText"
android:text="Click me to add text to the textview below without scrolling"/>
<Button
android:id="#+id/secondTextAddButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/firstTextAddButton"
android:layout_marginTop="380dp"
android:text="Click me to add text to the textview below and scroll (if you are currently scrolled all the way to the bottom)"/>
<TextView
android:id="#+id/textToEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/secondTextAddButton"
android:textSize="18sp"
android:text="Some text to get us started."/>
/>
</RelativeLayout>
</ScrollView>
And the code for the activity is as follows:
package code.example.scrollingontextchange;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class MainActivity extends Activity {
private int scroll_pos;
private int maxScrollPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView)findViewById(R.id.textToEdit);
tv.addTextChangedListener(new TextWatcher(){
#Override
public void afterTextChanged(Editable s) {
if(scroll_pos == maxScrollPosition)
{
Handler h = new android.os.Handler()
{
#Override
public void handleMessage(android.os.Message msg)
{
switch(msg.what)
{
case 0 :
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScrollView scrll = (ScrollView)findViewById(R.id.scrollmain);
scrll.fullScroll(ScrollView.FOCUS_DOWN);
break;
default :
break;
}
}
};
h.sendEmptyMessage(0);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
ScrollView scrll = (ScrollView)findViewById(R.id.scrollmain);
RelativeLayout rl = (RelativeLayout)findViewById(R.id.mainRelative);
scroll_pos = scrll.getScrollY();
maxScrollPosition = rl.getHeight() - scrll.getHeight();
}
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
});
OnClickListener addTextOnClick = new OnClickListener() {
#Override
public void onClick(View v) {
TextView tv = (TextView)findViewById(R.id.textToEdit);
tv.setText(tv.getText() + "\nA long time ago, in a galaxy s far far away............");
}
};
Button b = (Button)findViewById(R.id.firstTextAddButton);
b.setOnClickListener(addTextOnClick);
Button b2 = (Button)findViewById(R.id.secondTextAddButton);
b2.setOnClickListener(addTextOnClick);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Hope this helps.
Don't ask me why, but setting your TextView's gravity to bottom it does exactly what you want.