Please help!
I have a problem with creating a BitmapDrawable in a static context.
I am creating an android app for a student contest and since the MainActivity class starts
to look "dirty" (having lots of code in it) I decided to make MainActivityLayout class that extends the MainActivity. Basicly I moved some methods (the ones for setting layouts) from MainActivity to MainActivityLayout class. The problem is with resize() method where I use BitmapDrawable constructor wich is "bugging me slowly" because needs a reference to resources in order to resize properly the bitmap.
The MainActivity class :
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLayoutOne();
MainActivityLayouts.setLayoutOne();
getLayoutTwo();
MainActivityLayouts.setLayoutTwo();
}
private void getLayoutOne(){
//here I get the layouts id using findViewById() method
}
private void getLayoutTwo(){
//here I get the layout 2 id using findViewById() method
}
protected static Drawable resize(Drawable image,int xSize,int ySize) {
Bitmap b = ((BitmapDrawable)image).getBitmap();
Bitmap bitmapResized = Bitmap.createScaledBitmap(b, xSize, ySize, false);
return new BitmapDrawable(getResources(),bitmapResized);
}
}
The MainActivityLayout class:
public class MainActivityLayouts extends MainActivity{
public MainActivityLayouts(){
// ...
}
protected final static void setLayoutOne(){
Drawable drawableOne = ImageViewOne.getDrawable();
//here is the problem...cannot make a static refference...
//getResources() from resize method from MainActivity to be more specific
drawableOne = resize(drawableOne,100,100);
ImageViewOne.setImageDrawable(drawableOne);
}
protected final static void setLayoutTwo(){
Drawable drawableTwo = ImageViewTwo.getDrawable();
//here is the problem...cannot make a static refference...
//getResources() from resize method from MainActivity to be more specific
drawableTwo = resize(drawableTwo,200,200);
ImageViewTwo.setImageDrawable(drawableTwo);
}
Is there any solution to my problem? Resizing in another mode or can I avoid creating a BitmapDrawable and still obtain the same effect?
Any critic is highly appreciated :).
Related
I am trying to have what the user types in the textEdits in the StartScreen Activity to show up in my MainActivity.
First I created my 2 intents for the 2 users.
String playerOneContent = playerOneEditText.getText().toString();
String playerTwoContent = playerTwoEditText.getText().toString();
Intent intent = new Intent(StartScreen.this, GameView.class);
intent.putExtra("NAME", playerOneContent);
intent.putExtra("NAME2", playerTwoContent);
startActivity(intent);
Then in my GameView I have the following code:
public class GameView extends View {
Paint paint = new Paint();
Context context;
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
paint.setColor(Color.YELLOW);
canvas.drawPaint(paint);
paint.setColor(Color.RED);
paint.setTextSize(20);
canvas.drawText("NAME",50, 50, paint);
}
}
How would I get the intents from the StartScreen and use it in the GameView?
This is the code I had in my Main Activity originally:
TextView playerOneTextView = (TextView)findViewById(R.id.playerOneTextView);
TextView playerTwoTextView = (TextView)
findViewById(R.id.playerTwoTextView);
playerOneTextView.setText(getIntent().getStringExtra("NAME"));
playerTwoTextView.setText(getIntent().getStringExtra("NAME2"));
Unfortunately, intents don't work in Android without extending the Activity class.
Therefore, what you can do is create an object of the MainActivity class in your GameView class and get the value of the variables.
So something like this in MainActivity.java:
public String playerOneContent;
public String playerTwoContent;
#Override
public void onCreate...... //blah blah blah
public void functionWhereYouSetValueofStrings(){
playerOneContent = playerOneEditText.getText().toString();
playerTwoContent = playerTwoEditText.getText().toString();
}
Now, in the GameView.java class do the following to get the values:
MainActivity ma = new MainActivity();
playerOneTextView.setText(ma.playerOneContent);
playerTwoTextView.setText(ma.playerTwoContent);
It's using the Object to refer to the public fields that you have in MainActivity.java. I believe that this should answer your question, and help you.
If not, then just make a comment with the problem below.
I tried a lot of things but I can't get it to work... I try to pass this String Variable (when i click Item in RecyclerView) to my MainActivity.
What works bad is calling the function (OnRecyclerViewItemClick) and changing the variable(GetUrlFromItem). My version of Android Studio is 2.3.3
I really need do this:
My RecyclerView:
public class viewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView titulo;
Button playbtn01;
List<Fuente> ListaObjeto;
public viewHolder(View itemView,List<Fuente> datos) {
super(itemView);
ListaObjeto = datos;
titulo = (TextView) itemView.findViewById(R.id.texto);
playbtn01 = (Button) itemView.findViewById(R.id.playbtn00);
playbtn01.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int position = getAdapterPosition();
Fuente objeto = ListaObjeto.get(position);
if (view.getId() == playbtn01.getId()) {
MainActivity mainActivity = new MainActivity:
mainActivity.OnRecyclerViewItemClick(); /// initiate Void in Main
mainActivity.GetUrlFromItem = objeto.GetUrl; //Change Variable of Main
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
public String GetUrlFromItem;
public void OnRecyclerViewItemClick() {
if (GetUrlFromItem == "..."){
doSomething...
}
}
}
There are two big problems that I see.
The first is how you get a MainActivity instance to work with. In your question, you have this line of code:
MainActivity mainActivity = new MainActivity:
Calling new is going to do exactly what it sounds like: create a new instance of the MainActivity class. You do not want a new instance! You want your alive and running instance.
There are a handful of ways to get ahold of your alive and running MainActivity, but probably the simplest one for now is going to be casting your ViewHolder's itemView's Context. So instead of the above, write something like this:
MainActivity mainActivity = (MainActivity) itemView.getContext();
The second big problem is in the next two lines:
mainActivity.OnRecyclerViewItemClick();
mainActivity.GetUrlFromItem = objeto.GetUrl;
The problem here is the order of these two statements. Because you invoke mainActivity.OnRecyclerViewItemClick() before setting the value of mainActivity.GetUrlFromItem, the value will not be updated when OnRecyclerViewItemClick() is executed.
Simply swap the order of these two lines.
I'm unable to call methods of a custom view ("canvasview") from the Activity that sets the layout including the view. I can't even call canvasview's "getters" from the activity.
Also, I'm passing the view to a custom class (that does not extend Activity), and I can't call canvasview's methods also from my custom class.
I'm not sure what I'm doing wrong...
GameActivity.java:
public class GameActivity extends Activity implements OnClickListener
{
private View canvasview;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout);
canvasview = (View) findViewById(R.id.canvasview);
// Eclipse displays ERROR con those 2 method calls:
int w = canvasview.get_canvaswidth();
int h = canvasview.get_canvasheight();
(...)
game_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".GameActivity" >
(...)
<com.example.test.CanvasView
android:id="#+id/canvasview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
CanvasView.java:
public class CanvasView extends View
{
private Context context;
private View view;
private int canvaswidth;
private int canvasheight;
public CanvasView(Context context, AttributeSet attrs)
{
super(context, attrs);
this.context = context;
this.view = this;
}
#Override
protected void onSizeChanged(int width, int height,
int old_width, int old_height)
{
this.canvaswidth = width;
this.canvasheight = height;
super.onSizeChanged(width, height, old_width, old_height);
}
public int get_canvaswidth()
{
return this.canvaswidth;
}
public int get_canvasheight()
{
return this.canvasheight;
}
I'm quite confused with this :?
I also have another class (it does not extend "Activity") that receives in the constructor a reference to canvasview and is also unable to "resolve" it :?
Thanks, sorry if the question is too obvious, I'm starting with Java and those kind of things are quite confusing to me ...
EDIT:
While at bed (03:00AM), thinking about it, I've noticed that Eclipse marks the line as an error because the View object does not really have the method get_canvaswidth(). Only the child "CanvasView" method has it. Thus, my problem can be solved with upcast:
int w = ((CanvasView) canvasview).get_canvaswidth();
I mean that I receive a view as parameter, but as I now it's really a view child, I should be able to use upcast to call "child's" methods. Now eclipse does not generate errors but w and h always report 0 :-? . I've also tested of not using upcast as has been suggested in an answer, and sending and receiving CanvasView objects in the calls and I also get 0 for both :?
private View canvasview;
No matter what is stored in canvasview you can only call methods defined by the variable type. You need to change this line.
private CanvasView canvasview;
I am trying to call the view from another class in my Asynctask class but it doesn't seem to be working.
Here is my AsyncTack
private class parseSite extends AsyncTask<String, Void, List<Integer>> {
protected List<Integer> doInBackground(String... arg) {
List<Integer> output = new ArrayList<Integer>();
try {
htmlHelper hh = new htmlHelper(new URL(arg[0]));
output = hh.htmlHelper(arg[0]);
} catch (Exception e) {
System.out.println("Error");
}
return output;
}
protected void onPostExecute(List<Integer> exe) {
graph salesView = new graph();
View chartView = salesView.getView(this);
chartView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT, 1f));
LinearLayout layout = (LinearLayout) findViewById(R.id.linearview);
layout.addView(chartView, 0);
}
}
And here is what the activity 'graph' looks like
public class graph {
public View getView(Context context) (...etc.)
I don't understand why it can't call the view.
Assuming you intended graph to extend Context in some way, such as by extending Activity, and that parseSite is defined inside graph, make the following change:
View chartView = salesView.getView(graph.this);
In the original code, this is referring to parseSite which does not extend Context (and does not refer to graph as you probably intend).
As a side note, in typical Java style classes should be named with an upper case letter, i.e. Graph not graph.
I think the problem is that you try to access view from other thread that created it. Usual way is to use runOnUiThread():
(activity).runOnUiThread(new Runnable() {
public void run() {
//call anything to your View objects
}
});
Below is my coding where it would load the image when this Activity is called. But i wished to display the progressDialog when it was retrieving the images from the server instead of just a black screen presented to the user. I heard that AsyncTask is able to do but i stuck with where to place the AsyncTask function and calling it.
public class LargeImageScroller extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static Bitmap bmLargeImage; //bitmap large enough to be scrolled
private static Rect displayRect = null; //rect we display to
private Rect scrollRect = null; //rect we scroll over our bitmap with
private int scrollRectX = 0; //current left location of scroll rect
private int scrollRectY = 0; //current top location of scroll rect
private float scrollByX = 0; //x amount to scroll by
private float scrollByY = 0; //y amount to scroll by
private float startX = 0; //track x from one ACTION_MOVE to the next
private float startY = 0; //track y from one ACTION_MOVE to the next
public SampleView(Context context) {
super(context);
displayRect = new Rect(0, 0, displayWidth, displayHeight);
scrollRect = new Rect(0, 0, displayWidth, displayHeight);
bmLargeImage = Bitmap.createBitmap(1035 , 665, Config.ARGB_8888);
bmLargeImage = createMap(this.getContext());
}
public boolean onTouchEvent(MotionEvent event) {....}
protected void onDraw(Canvas canvas) {....}
private static Bitmap createMap(Context context) {...}
private static Drawable LoadImageFromWebOperations(String url) {....}
private static Bitmap decodeFile(File f, int requiredSize) {...}
}
}
I wish to know where should i place the AsyncTask function so as to display the progressDialog while the program is loading the image from server/cache. Most of the source i found on the internet doesn't say much.
AsyncTask is somehow like a Thread. It is used to handle some time-consuming operations so that the main thread won't be blocked.
In your case, AsyncTask is suitable. However, the place where you would like to put it depends on your logic.
Please read the SDK: AsyncTask to get more info about it. There is also a code snippet that may help you.
Added:
Well, I understand your concern. If you just want to show a progress bar to tell the users that the app is downloading the images from the server. You may handle this way:
1. Create a xml layout file containing a ProgressBar.
2. In OnCreate in Class LargeImageScroller, call setContentView(R.layout.that_layout) to show the progressbar, and Start a AsyncTask to download the images.
3.Inside AsyncTask, override onProgressUpdate(Integer... progress) to tell the ProgressBar the donwloading progress.
4. Inside AsyncTask, override onPostExecute(Long result). This method will be called when the AsyncTask finishes. Here you can do : SampleView sv=new SampleView(this), and then pass the images to the sv object. Then call setContentView(sv) to show your images.
This is just my train of thought. I think you can use AsyncTask in either LargeImageScroller class or SampleView class. Hope ithis comment helps.