Considering the example from the below image,
I'm looking for a solution to pass the touch events from the canvas View to the Viewpager. This is necessary for applying the same amount of zoom on both views at the same time.
Here's the technical description of what's going on,
(Lets consider the view as A, B & C)
A. Parent View
B. View
C. View Pager
Before the dispatchTouchEvent() is called on the children (B & C), the A.dispatchTouchEvent() will first calls A.onInterceptTouchEvent() to see if the view group is interested in intercepting the event.
So if A.onTouchEvent() returns false, then it goes back up to B.onTouchEvent(). If that returns false then it goes back up to C.onTouchEvent() and the dispatching continues as usual.
And upon returning true,
ACTION_CANCEL will be dispatched to all the children.
All the subsequent gesture events (till ACTION_UP/ACTION_CANCEL) will be consumed by the event listeners (OnTouchListener.onTouch()) if defined, else the event handler A.onTouchEvent() at A’s level.
At this point I can pass the events from the parent to the child views but can't let the 2 child view B. & C handle the events together (applying same amount of zoom on both views).
Is there any way to pass the touch events from the parent view to a child one so that they can process the events simultaneously?
Here's my layout setup,
<RelativeLayout
android:id="#+id/layoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFFFF">
<com.androidapp.NonSwipeableViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#color/transparent" />
<com.androidapp.DrawingView
android:id="#+id/drawing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent" />
</RelativeLayout>
If I'm not wrong, you want to process the same touch event both on the top and bottom view. According to Android touch architecture, you can't handle touch events from multiple views at the same time. Either you have to process it inside the onTouchEvent() method or pass to the next view. You also need to wait till the top view finish processing the MotionEvent() and let the child view to handle.
Here's a possible solution using RxAndroid approach,
Inside your canvas view's MotionEvent(),
#Override
public boolean onTouchEvent(MotionEvent event) {
// process all touch events (UP/DOWN/MOVE)
//send events as observable
RxBus.getInstance().sendMotionEvent(event);
return true;
}
This will observe the motion events and notify all observers.
Now, inside your viewpager's onResume() subscribe for the motion events so that whenever a change is made from the canvas It'll immediately pass the events.
Subscription RxBus _rxBus = RxBus.getInstance();
subscription = _rxBus.getMotionEvent()
.subscribe(new Action1<MotionEvent>() {
#Override
public void call(MotionEvent event) {
// call the onTouchEvent of your widget e.g. ImageView and pass the received event
// this will apply the same touch event that was applied in the canvas
// .onTouchEvent(event) is important to override the onTouchEvent() of your widget that will use the touch event
imageView.onTouchEvent(event);
}
});
The RxBus class is given below,
public class RxBus {
private static RxBus instance;
private final PublishSubject<MotionEvent> motion_event = PublishSubject.create();
public static RxBus getInstance() {
if (instance == null) {
instance = new RxBus();
}
return instance;
}
public void sendMotionEvent(MotionEvent motionEvent) {
motion_event.onNext(motionEvent);
}
public Observable<MotionEvent> getMotionEvent() {
return motion_event;
}
}
It is pretty easy to implement by using call back. Just create an Interface with whatever methods, you need and then implement in your Viewpager. Call will be invoked in your View class based on your touch events and responds will come to Viewpager. I have created an example with an ImageView in my MainActivity and called to changed its size from a different fragment and it works. Here is my code below:
public interface ICallBackForResize {
void resizeme();
void actionUp();
void actionDown();
}
MainActivity:
public class MainActivity extends AppCompatActivity implements ICallBackForResize {
ImageView img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img= (ImageView) findViewById(R.id.image);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void resizeme() {
Toast.makeText(MainActivity.this,"called",Toast.LENGTH_LONG).show();
img.getLayoutParams().height += 20;
img.getLayoutParams().width += 20;
img.requestLayout();
}
#Override
public void actionUp() {
//do whatever
}
#Override
public void actionDown() {
//do whatever
}
}
My Fragment class with a simple button:
public class MyFragmentButton extends Fragment {
View view;
ICallBackForResize callBackForResize;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
callBackForResize= (ICallBackForResize) getActivity();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.mybutton,container,false);
Button btn= (Button) view.findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callBackForResize.resizeme();
}
});
return view;
}
}
I believe you dont need xml file. I just shared if somebody needs:
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main"/>
</android.support.design.widget.CoordinatorLayout>
content_main:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_main"
tools:context="nanofaroque.com.addlistener.MainActivity">
<ImageView
android:id="#+id/image"
android:text="Hello World!"
android:layout_width="100dp"
android:layout_gravity="center"
android:src="#mipmap/ic_launcher"
android:layout_height="100dp" />
<fragment
android:name="nanofaroque.com.addlistener.MyFragmentButton"
android:id="#+id/headlines_fragment"
android:layout_width="100dp"
android:layout_height="100dp" />
</FrameLayout>
mybutton:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Related
I am using onTouchEvent to capture clicks on buttons. These buttons are in views, inflated in the main view.
My problem is that I have to click twice time on the screen to get my onTouchEvent triggered.
I found a similar topic telling to call setContentView after inflating but my app contains many other things so I just cannot call setContentView each time I inflate a new view.
activity_main.xml :
<RelativeLayout android:id="#+id/activity_main"
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="com.pixeemedical.kneeplus.MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto">
... other stuff here
<RelativeLayout
android:id="#+id/rlayout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
</RelativeLayout>
</RelativeLayout>
My ActivityMain.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainLayout = findViewById(R.id.rlayout_content);
mMainLayout.removeAllViews();
View currentLayoutToAdd = LayoutInflater.from(this).inflate(R.layout.layout_to_inflate, mMainLayout, false);
mMainLayout.addView(currentLayoutToAdd, 0);
Button btn = findViewById(R.id.btn);
btn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// called only after second click
}
});
}
}
I am new to Android TV development. I don't know which type of fragment to use. I want two achieve layout similar to above screenshot as jiocinema. Somehow I have achieved it using a two xml fragments inside activity layout. Second fragments loads screenshot after hitting an API so it loads after some time. As can be seen in the above screenshot I want the layout in two parts..top one with details and some buttons and the bottom one is a list of screenshots of that movie.
In my case the problem is, bottom list part takes the focus on loading this particular screen after that on pressing up button or any button it never loses focus and never goes on the top part.
Note: below fragment loads asynchronously, as it hits an api for screenshot urls
May be I haven't used proper fragments for this particular layout. Can someone point me to the code or help me out in deciding what to use for this kind of layout. As it can be achieved but navigation is the main thing.
code
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/photo_label_box">
<fragment
android:id="#+id/detail_layout"
android:layout_width="match_parent"
android:name="com.DetailsActivityGame$Detalfragment"
android:layout_height="200dp"></fragment>
<fragment
android:id="#+id/row_layout"
android:layout_width="match_parent"
android:layout_below="#+id/detail_layout"
android:name="com.DetailsActivityGame$SampleFragmentC"
android:layout_height="wrap_content"></fragment>
</RelativeLayout>
Thanks
Try to use the RowSupportFragment in V4 Support Fragment for desired output.
Divide layout into two parts layout with buttons, description and below scrolling layout(Represent by RowSupportFragment)
//----------------------detail_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/leader_background">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/main_layout"
//your own layout design for buttons and description
</RelativeLayout>
<fragment
android:name="FragmentScreenshots"
android:id="#+id/screenshot_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
//----------------Detailfragment--------------------
public static class Detailfragment extends Fragment {
public Detailfragment(){ }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.detail_layout, container, false);
//————————your own implementation—————————————————————————
return view;
}
public static class FragmentScreenshots extends RowsSupportFragment {
private ArrayObjectAdapter mRowsAdapter = null;
public FragmentScreenshots() {
mRowsAdapter = new ArrayObjectAdapter(new ShadowRowPresenterSelector());
setAdapter(mRowsAdapter);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//———————Provide data accordinally———————————
List<ScreenshotItem> list;
// Add a Related items row
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
new ScreenshotCardPresenter(getActivity()));
for (ScreenshotItem s:list)
{
listRowAdapter.add(s);
}
HeaderItem header = new HeaderItem("Screenshots");
mRowsAdapter.add(new ListRow(header, listRowAdapter));
setAdapter(mRowsAdapter);
setOnItemViewClickedListener(new OnItemViewClickedListener() {
#Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
if (item instanceof ScreenshotItem) {
}
else{
}
}
});
setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
#Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
}
});
}
#Override
public void setExpand(boolean expand) {
super.setExpand(true);
}
#Override
public void setOnItemViewClickedListener(BaseOnItemViewClickedListener listener) {
super.setOnItemViewClickedListener(listener);
}
#Override
public void setOnItemViewSelectedListener(BaseOnItemViewSelectedListener listener) {
super.setOnItemViewSelectedListener(listener);
}
}}
You have to use BrowseFragment for your purpose. It is composed of a RowsFragment and a HeadersFragment.
A BrowseFragment renders the elements of its ObjectAdapter as a set of rows in a vertical list. The elements in this adapter must be subclasses of Row.
This tutorial can help you to get started.
I was so inspired by this feature of coordinator layout (link to post):
There’s another, more heavy handed touch interception though: blocking
all interactions whatsoever. Just return true in
blocksInteractionBelow() and that’s it. Of course, you probably want
to have some visual signal that interactions are blocked (lest they
think the app is completely broken) — that’s why the default
functionality of blocksInteractionBelow() actually relies on the value
of getScrimOpacity() — return a non-zero value here will both paint an
overlay color over the View (of color getScrimColor(), defaulting to
black) and disable touch interactions all in one swoop. Handy.
I have an activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_main);
}
public void click(View view) {
Toast.makeText(this, "Go", Toast.LENGTH_SHORT).show();
}
}
layout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Go"
android:onClick="click"
android:elevation="0dp"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="200dp"
android:background="#409"
app:layout_behavior=".B"
android:elevation="16dp"
/>
</android.support.design.widget.CoordinatorLayout>
and behavior
public class B extends CoordinatorLayout.Behavior<View> {
public B(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public float getScrimOpacity(CoordinatorLayout parent, View child) {
return .8f;
}
#Override
public int getScrimColor(CoordinatorLayout parent, View child) {
return Color.RED;
}
}
But unfortunately, as a result - click on button still works and button is not overlaping by scrim color.
Hope somebody knows what am i doing wrong. Thanks.
How can I create an onTouchListener for a frame that only houses a fragment? I don't need to inflate an activity_main file as it will already be displayed by the time this fragment is called. If I try to inflate the frame itself it throws a "expected resource of type layout" error.
The fragment will be activated when a user touches a button and the fragment should open in the frame. The frame also needs to be able to listen to touch events.
This is what my Fragment and onCreateView for the fragment looks like right now:
public class TeacherFragment extends Fragment {
public final String TAG = getClass().getSimpleName();
public void onAttach(Activity myActivity){
Log.v(TAG, "in TeacherFragment - onAttach, activity is: " + myActivity);
super.onAttach(myActivity);
}
/**
* This method will only be called once when the retained
* Fragment is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
}
/**
* This method will be called only when
* Fragment is attached and ready to display the view.
*/
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle SavedInstanceState){
if(container == null) {
Log.v(TAG, "container is null. No need to inflate.");
return null;
}
View v = container.findViewById(R.id.assignment_view);
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "onShortPress: " + event.toString());
Toast.makeText(getView().getContext(), "Testing Short click", Toast.LENGTH_SHORT).show();
return true;
}
public void onLongPress(MotionEvent event) {
Log.d(TAG, "onLongPress: " + event.toString());
Toast.makeText(getView().getContext(), "Testing Long click", Toast.LENGTH_SHORT).show();
}
});
return v;
} //end onCreateView
}
Here is my activity_main. I am trying to use the assignment_view frame only for this Fragment.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_layout"
android:baselineAligned="false">
<FrameLayout
android:id="#+id/main_menu_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#FF0000"
android:layout_weight=".3">
</FrameLayout>
<FrameLayout
android:layout_width="8dp"
android:layout_height="match_parent"
android:background="#000000">
</FrameLayout>
<FrameLayout
android:id="#+id/assignment_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00BBFF"
android:layout_weight="8">
</FrameLayout>
</LinearLayout>
You should only use inflate() on a file. One that's in your "layout" folder. This is what the error message is telling you. Without spending a lot of time looking at this, you probably want this
View v = findViewById(R.id.assignment_view);
As far as inflating your "activity_main.xml" file, it's probably better to inflate it here than rely on what was inflated in the calling activity.
Im developing a contacts app, and for now Ive been trying to get this drawables from the array get uploaded into the Gridview on the main screen AFTER the save mosaic button is clicked in the mosaic creation screen.
the floating action button (red plus button) on the mosaicListScreen (main screen) leads to the MosaicCreationScreen). the user hypothetically uploads the image and enters the mosaic name then saves using the save mosaic button, as can be seen in the image here
For now, before I focus on uploading image and letting the user create their own unique mosaics (groups), Im testing the Gridview updating with some drawables, which are listed in the array as can be seen in the code below.
The issue thats occuring is as soon as the user clicks the floating action button on the main screen, it updates the gridview with the drawables listed in the array of the MosaicCreation Screen, THEN it goes to the MosaicCreationScreen, and when save mosaic button is clicked on the MosaicCreationScreen, the intent goes to the main screen as its supposed to do, except the gridview will have nothing on it.
so its like its doing the opposite of whats supposed to happen in steps.
here is my code for the two screens:
public class mosaicsListScreen extends AppCompatActivity {
public static mosaicsListScreen theScreen; //this variable is used in the MosaicCreationScreen to point to this screen to find the GridView by id
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theScreen = this;
setContentView(R.layout.activity_mosaics_list_screen);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.createMosaicButton);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(),MosaicCreationScreen.class);
startActivity(intent);
finish();
}
});
}
}
here is the code for the MosaicCreationScreen (the one that opens after user clicks floating action button from mosaicListScreen (main screen))
public class MosaicCreationScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mosaic_creation_screen);
final GridView mosaicList = (GridView) mosaicsListScreen.theScreen.findViewById(R.id.mosaicList);
mosaicList.setAdapter(new ImageAdapter(this)); //this line of code displays the mosaics on mosaicListScreen
Button saveNewMosaicButton = (Button) findViewById(R.id.saveNewMosaicButton);
saveNewMosaicButton.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View view) {
//mThumbIds.notify();
Intent intent = new Intent(getApplicationContext(), mosaicsListScreen.class);
startActivity(intent);
finish();
//mosaicList.setAdapter(new ImageAdapter(this)); //this displays the mosaics on mosaicListScreen, it logically should go here, however "this" causes an error saying ImageAdapter (android.content.Context) in ImageAdapter cannot be applied to (anonymous android.view.View.OnClickListener)
Toast.makeText(mosaicsListScreen.theScreen, "Mosaic Created!", Toast.LENGTH_SHORT).show();
}
});
/* mosaicList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(mosaicsListScreen.theScreen, "", Toast.LENGTH_SHORT).show();
}
});*/
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
//this array holds the drawables that would appear on the Gridview
private Integer[] mThumbIds = {
R.drawable.family,
R.drawable.project
};
}
}
Here are the XML for the layouts:
content_mosaics_list_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="codesages.mosaic.mosaicsListScreen"
tools:showIn="#layout/activity_mosaics_list_screen">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/create_a_mosaic_or_pick_from_the_mosaics_created"
android:id="#+id/textView4"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="20sp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/deleteMosaicButton"
android:src="#android:drawable/ic_menu_delete"
android:clickable="true"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:contentDescription="" />
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/textView4"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="14dp"
android:id="#+id/mosaicList"
android:layout_above="#+id/textView7"
android:numColumns="auto_fit" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="#string/holdMosaictoDeleteLabel"
android:id="#+id/textView7"
android:layout_marginBottom="16dp"
android:layout_above="#+id/deleteMosaicButton"
android:layout_centerHorizontal="true" />
</RelativeLayout>
activity_mosaics_list_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<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="codesages.mosaic.mosaicsListScreen">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/createMosaicButton"
android:layout_width="56dp"
android:layout_height="66dp"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_input_add" />
<include layout="#layout/content_mosaics_list_screen" />
</android.support.design.widget.CoordinatorLayout>
activity_mosaic_creation_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<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="codesages.mosaic.MosaicCreationScreen"
android:focusable="true">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/mosaicNametextField"
android:hint="Mosaic Name"
android:layout_marginTop="81dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save New Mosaic"
android:id="#+id/saveNewMosaicButton"
android:layout_marginTop="48dp"
android:layout_below="#+id/uploadMosaicImageButton"
android:layout_centerHorizontal="true"
android:enabled="true"
android:clickable="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload Mosaic Image"
android:id="#+id/uploadMosaicImageButton"
android:layout_marginTop="68dp"
android:layout_below="#+id/mosaicNametextField"
android:layout_centerHorizontal="true"
android:enabled="true"
android:clickable="true" />
</RelativeLayout>
mosaicList.setAdapter(new ImageAdapter(this));
thats what appears to be creating the mosaics. if i comment this out, i wont see anything in the gridview.
however, i believe that should be inside the saveNewMosaicButton onClick, but I am getting an error that says "saying ImageAdapter (android.content.Context) in ImageAdapter cannot be applied to (anonymous android.view.View.OnClickListener)"
HERE is an image example of what the desired result should be. however whats happening right now is as ive stated, as soon as the floating action button is clicked, the mosaics are created, THEN it takes you to the creation screen, in which wehn i click save mosaics, it actually erases the mosaics...a job of the trash icon which is too soon to function for now heh.
appreciate help on this
Currently, you have
public static mosaicsListScreen theScreen;
in your first Activity which you use to fill the ListView in this first Activity. This is a dangerous approach because the Activity instance referenced by this variable may be destroyed, for example if you're doing work in your second Activity (e.g. downloading images) which uses much memory, but also if the user somehow triggers a configuration change.
As you are calling finish() after starting the second Activity, you even tell the system that the first Activity may be destroyed. The only reason you did not get a NPE is that the system destroys the finished Activity not instantly but as soon as it seems a good idea to do so.
All in all, you need a way to safely transmit information from one Activity to the other. In your case, I think you would like to send the Uri of the selected images ( or for now, send the resource id of the selected drawables). Both can be accomplished by using Intent extras.
Basically, there are two options:
use startActivityForResult() and override onActivityResult() to obtain the desired information for the first Activity
simply start the first Activity from the second Activity once you have the result and use getIntent() in the first Activity (e.g. in onCreate()) to check for results
No matter what you do, always access UI elements like the ListView in the Activity to which they belong!
If you choose the second option, your first Activity could look like this:
public class mosaicsListScreen extends AppCompatActivity {
public static final String THUMB_IDS = "someuniquestring";
private GridView mosaicList;
private ArrayList<Integer> mThumbIds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mosaics_list_screen);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.createMosaicButton);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(),MosaicCreationScreen.class);
startActivity(intent);
finish();
}
});
fillThumbIds();
mosaicList = (GridView) findViewById(R.id.mosaicList);
// Note: Adapter code in this Activity
mosaicList.setAdapter(new ImageAdapter(this));
}
private void fillThumbIds()
{
mThumbIds = new ArrayList();
// somehow get older thumb ids if necessary (from database?)
// and add to ArrayList like this:
mThumbIds.add(R.drawable.family);
mThumbIds.add(R.drawable.project);
// assuming we transmit resource id's: use an int array with the Intent
int[] newThumbIds = getIntent().getIntArrayExtra(THUMB_IDS);
if (newThumbIds != null)
{
// loop through the array to add new thumb ids
for (int i = 0; i < newThumbIds.length; i++) {
mThumbIds.add(newThumbIds[i]);
}
}
}
// Adapter code goes here
// Note: thumbIds no longer as array but as ArrayList!
}
In the second Activity, you put the selected thumb ids as Intent extra as follows:
saveNewMosaicButton.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), mosaicsListScreen.class);
// if 'myNewThumbs' is the int array with the new thumb ids
intent.putExtra(mosaicsListScreen.THUMB_IDS, myNewThumbs);
startActivity(intent);
finish();
}
});