I have added custom imageview to viewpager, while setting matrix to canvas of customimageview , the customimageview doesn't drag with viepager movement
(like it is fixed in the same place). I couldn't realize what the problem.
//this is my simeple ImagePagerAdapter of viewpager
public class ImagePagerAdapter extends FragmentStatePagerAdapter {
private TabPageIndicator indicator;
private final int mSize;
private PageFragment pageFragment;
public ImagePagerAdapter(FragmentManager fm, int size) {
super(fm);
mSize = size;
}
#Override
public int getCount() {
return mSize;
}
#Override
public Fragment getItem(int position) {
PageMatrixFragment fragment = new PageMatrixFragment(position);
return fragment;
}
}
public class PageMatrixFragment extends Fragment {
int pos;
public PageMatrixFragment(int pos) {
this.pos = pos;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
CustomImageView customImageView = new CustomImageView(getActivity());
if (pos % 2==0) {
customImageView.setBackgroundColor(Color.RED);
}else{
customImageView.setBackgroundColor(Color.BLUE);
}
return customImageView;
}
}
public class CustomImageView extends ImageView {
private Bitmap mMarker;
public CustomImageView(Context context) {
super(context);
init();
}
private void init() {
mMarker = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
protected void onDraw(Canvas c) {
super.onDraw(c);
Matrix matrix = new Matrix();
float[] values =
{1, 0, 50,
0, 1, 50,
0, 0, 1};
matrix.setValues(values);
//problems accure when I use this line it forces the movement of customimageview with viewpager
c.setMatrix(matrix);
Paint paint = new Paint();
c.drawBitmap(mMarker, 200, 200, paint);
}
}
The first screenshot shows the start state ,
when I commented matrix.setValues(values); line it works as should work like in 2_nd screenshot
while I need to apply matrix to canvas ,but it causes the result like it is in 3_rd screenshot ,it doesn't move with viewpager/
Related
I have a fragment class Frag2 and a view class Rectangle which sends onDraw to another fragment class Frag1, and i need to send some data to Rectangle from Frag 2.
what do i do ? :D
(sorry its abit messy ive been trying everything for last 24 hours.)
Frag 2
public class FragmentTwo extends Fragment {
TextView changingText;
Button changeTextButton;
Button XButton;
Button YButton;
private int SecondX;
NumberPicker Pick100 = null;
private int entered;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View myInflatedView = inflater.inflate(R.layout.fragment_two_layout, container, false);
changingText = (TextView) myInflatedView.findViewById(R.id.textView);
changeTextButton = (Button) myInflatedView.findViewById(R.id.button);
XButton = (Button) myInflatedView.findViewById(R.id.buttonX);
YButton = (Button) myInflatedView.findViewById(R.id.buttonY);
Pick100 = (NumberPicker) myInflatedView.findViewById(R.id.secondD);
changeTextViewValueRandomlyOnButtonClick();
return myInflatedView;
}
private void changeTextViewValueRandomlyOnButtonClick() {
final String[] text = {"A", "B", "C", "D"};
changeTextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Random rand = new Random();
int random = rand.nextInt(100) + 1;
if (random == 100) changingText.setText(text[3]);
if (random > 90 && random <= 99) changingText.setText(text[2]);
if (random < 60 && random >= 1) changingText.setText(text[0]);
if (random >= 60 && random <= 90) changingText.setText(text[1]);
}
});
}
You can ignore most of it really. Im trying to send Pick100 to this class
public class Rectangle extends View {
//FragmentTwo F2 = new FragmentTwo();
public Rectangle(Context context) {
super(context);
}
public Rectangle(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public Rectangle(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("X","RED DOT EUQALS TO "+x);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawRect(x,100,x+60,100+60,paint);
}
}
The Rectangle works fine.It sends a rect to Frag1 i just want to be able to send the number here and sub it in x ( int rectangle)
Frag 1 class :
public class FragmentOne extends Fragment {
RelativeLayout relativeLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View myInflatedView= inflater.inflate(R.layout.fragment_one_layout,container,false);
return myInflatedView;
}
}
Frag 1 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:id="#+id/Frag1"
android:layout_height="match_parent"
android:background="#000">
<com.redot.puzzle1.Rectangle
android:id="#+id/Rect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
I am fairly sure you can simply define a void setX(int x) in the Rectangle class.
In whatever Fragment you've put the Rectangle View, you would need something like
// Make a field for this
rect = (Rectangle) myInflatedView.findViewById(R.id.Rect);
// Call your method whenever
rect.setX(x);
Note: Looks like you are trying to randomly change the size of a view and expecting the onDraw method to do that change.
I think you should be using a Canvas object instead if you want to be working with Shapes and such
Create a static field in Rectangle class public static int pick100Value = 0 and subtract pick100Value from x in onDraw()
public class Rectangle extends View {
public static int pick100Value = 0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// ...
canvas.drawRect(x - pick100Value , 100, (x - pick100Value) + 60, 100 + 60, paint);
}
}
In FragmentTwo listen to the onValueChanged and set Rectangle.pick100Value = newVal
public class FragmentTwo extends Fragment implements OnValueChangeListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
View myInflatedView = inflater.inflate(R.layout.fragment_two_layout, container, false);
changingText = (TextView) myInflatedView.findViewById(R.id.textView);
changeTextButton = (Button) myInflatedView.findViewById(R.id.button);
XButton = (Button) myInflatedView.findViewById(R.id.buttonX);
YButton = (Button) myInflatedView.findViewById(R.id.buttonY);
Pick100 = (NumberPicker) myInflatedView.findViewById(R.id.secondD);
Pick100.setOnValueChangedListener(this);
changeTextViewValueRandomlyOnButtonClick();
return myInflatedView;
}
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
Rectangle.pick100Value = newVal;
}
}
Bear with me, I am very new to Android dev. I'm trying to make a simple app with 9 cards arranged in a 3x3 grid. To do this, I decided to use the GridView layout along with a custom View for each card. I based it mostly on the GridView guide.
Here is what I have:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_cards"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3"
android:stretchMode="columnWidth"
android:gravity="center"
/>
MainActivity.java
public class MainActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView grid_cards = (GridView) findViewById(R.id.grid_cards);
grid_cards.setAdapter(new CardAdapter(this));
grid_cards.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(MainActivity.this, "position = " + position,
Toast.LENGTH_SHORT).show();
}
});
}
}
CardAdapter.java
public class CardAdapter extends BaseAdapter {
private Context mContext;
private int mSize;
public CardAdapter(Context c) {
mContext = c;
mSize = 9;
}
public int getCount() {
return mSize;
}
public Object getItem(int position) {
return null; // XXX
}
public long getItemId(int position) {
return 0; // XXX
}
public View getView(int position, View convertView, ViewGroup parent) {
CardView cardView;
if (convertView == null) { // if it's not recycled, initialize some attributes
cardView = new CardView(mContext);
cardView.setBackgroundColor(Color.WHITE);
} else {
cardView = (CardView) convertView;
}
// force redraw. XXX: truly required?
cardView.invalidate();
return cardView;
}
}
CardView.java
public class CardView extends View {
Paint paint = new Paint();
public CardView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(1);
canvas.drawRect(0, 0,
canvas.getWidth()-1,
canvas.getHeight()-1, paint);
}
}
What I get instead is nothing. The app does not crash, but none of the cards are drawn. Adding some Log.i() calls seems to indicate that the onDraw() of CardView is not even called. What am I doing wrong?
Thanks!
Your error is that you never called super.onDraw(canvas)
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas); //<== this line is needed to begin drawing on the canvas
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(1);
canvas.drawRect(0, 0,
canvas.getWidth()-1,
canvas.getHeight()-1, paint);
}
you need to explicitly set the derived View dimensions using setMinimumWidth() and setMinimumHeight()
I have the following views: a ViewPager that show 3 Fragments. The user can scroll horizontaly to see the others Fragment in the ViewPager.
I need to create an animation, when the Activity is created and the ViewPager is populated, that show the Fragments entering from the right side of the screen.
Is that even possible? Thanks.
XML:
<android.support.v4.view.ViewPager
android:id="#+id/devices"
android:layout_width="wrap_content"
android:layout_height="150dp" />
Activity:
MyFragmentStatePagerAdapter mAdapter = new MyFragmentStatePagerAdapter( this.getSupportFragmentManager(), fragmentArrayList );
mAdapter.setPageWidth(0.33333333f);
ViewPager devices = (ViewPager) view.findViewById(R.id.devices);
devices.setAdapter(sensorAdapter);
Adapter:
public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
ArrayList<Fragment> fragmentsList;
private float pageWidth = 1;
public void setPageWidth(float pageWidth) { this.pageWidth = pageWidth; }
public MyFragmentStatePagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentsList) {
super(fm);
this.fragmentsList = fragmentsList;
}
#Override
public int getCount() {
return fragmentsList.size();
}
#Override
public Fragment getItem(int position) {
if (position<fragmentsList.size() & fragmentsList.get(position)!=null) {
return fragmentsList.get(position);
}
return null;
}
#Override
public float getPageWidth(int position) {
return(pageWidth);
}
}
OK, I found the solution. I just had to extend ViewPager and do the animation in onDraw.
This code is working as I needed:
public class ViewPagerCustom extends ViewPager {
private Context mContext;
private boolean startAnimationDone = false;
public ViewPagerCustom(Context context) {
super(context);
mContext = context;
init();
}
public ViewPagerCustom(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
DisplayMetrics metrics;
TranslateAnimation anim;
private void init() {
metrics = mContext.getResources().getDisplayMetrics();
anim = new TranslateAnimation(metrics.widthPixels+200, 0, 0, 0);
anim.setInterpolator(new DecelerateInterpolator());
anim.setDuration(500);
}
private Canvas enterAnimation(Canvas c) {
startAnimationDone = true;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
child.startAnimation(anim);
}
return c;
}
#Override
protected void onDraw(Canvas c) {
if (startAnimationDone==false) {
c = enterAnimation(c);
}
super.onDraw(c);
}
}
Here is a link which might help you:
Zoom-out page transformer
It's similar to the accepted solution but uses the same interpolator and only changes the duration based on a factor. You need to use a ViewPagerCustomDuration in your XML instead of ViewPager, and then you can do this:
ViewPagerCustomDuration vp = (ViewPagerCustomDuration) findViewById(R.id.myPager);
vp.setScrollDurationFactor(2); // make the animation twice as slow
I want to create a ViewPager, but when I execute the application in my phone, it shows me a blank activity and then the following error message:
The application testViewPager (process com.example.testviewpager) has stopped unexpectedly. Please try again.
How can I go about fixing this problem?
Main.xml:
<?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="match_parent">
<com.example.testviewpager.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#CCC">
<android.support.v4.view.ViewPager
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal" />
</com.example.testviewpager.PagerContainer>
</RelativeLayout>
PagerActivity.java:
public class PagerActivity extends Activity {
PagerContainer mContainer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContainer = (PagerContainer) findViewById(R.id.pager_container);
ViewPager pager = mContainer.getViewPager();
PagerAdapter adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
//Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
pager.setOffscreenPageLimit(adapter.getCount());
//A little space between pages
pager.setPageMargin(15);
//If hardware acceleration is enabled, you should also remove
// clipping on the pager for its children.
pager.setClipChildren(false);
}
//Nothing special about this adapter, just throwing up colored views for demo
private class MyPagerAdapter extends PagerAdapter {
#Override
public Object instantiateItem(ViewGroup container, int position) {
TextView view = new TextView(PagerActivity.this);
view.setText("Item "+position);
view.setGravity(Gravity.CENTER);
view.setBackgroundColor(Color.argb(255, position * 50, position * 10, position * 50));
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
}
PagerContainer.java:
public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener {
private ViewPager mPager;
boolean mNeedsRedraw = false;
public PagerContainer(Context context) {
super(context);
init();
}
public PagerContainer(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PagerContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setClipChildren(false);
}
#Override
protected void onFinishInflate() {
try {
mPager = (ViewPager) getChildAt(0);
mPager.setOnPageChangeListener(this);
} catch (Exception e) {
throw new IllegalStateException("The root child of PagerContainer must be a ViewPager");
}
}
public ViewPager getViewPager() {
return mPager;
}
private Point mCenter = new Point();
private Point mInitialTouch = new Point();
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenter.x = w / 2;
mCenter.y = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
//We capture any touches not already handled by the ViewPager
// to implement scrolling from a touch outside the pager bounds.
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialTouch.x = (int)ev.getX();
mInitialTouch.y = (int)ev.getY();
default:
ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y);
break;
}
return mPager.dispatchTouchEvent(ev);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Force the container to redraw on scrolling.
//Without this the outer pages render initially and then stay static
if (mNeedsRedraw) invalidate();
}
#Override
public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE);
}
}
MainActivity.java:
public class MainActivity extends Activity
{
PagerContainer mContainer;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (PagerContainer) findViewById(R.id.pager_container);
ViewPager pager = mContainer.getViewPager();
PagerAdapter adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
// Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
pager.setOffscreenPageLimit(adapter.getCount());
// A little space between pages
pager.setPageMargin(15);
}
// Nothing special about this adapter, just throwing up colored views for
// demo
private class MyPagerAdapter extends PagerAdapter
{
#Override
public Object instantiateItem(ViewGroup container, int position)
{
TextView view = new TextView(MainActivity.this);
view.setText("Item " + position);
view.setGravity(Gravity.CENTER);
view.setBackgroundColor(Color.argb(255, position * 50,
position * 10, position * 50));
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView((View) object);
}
#Override
public int getCount()
{
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object)
{
return (view == object);
}
}
}
ImageRenderer.java
public class ImageRenderer implements Renderer {
...
private Context mActivityContext;
...
public SandAniRenderer(final Context activityContext) {
// TODO Auto-generated constructor stub
mActivityContext = activityContext;
mField = new Field(mActivityContext);
...
}
private boolean InitializeObject(int width, int height)
{
...
Field.SetField(width, height, R.drawable.image);
...
return true;
}
Field.java
public class Field extends xxx{
private final Context mActivityContext;
public Field(Context activityContext)
{
mActivityContext = activityContext;
}
public boolean SetField(int width, int height, int fn)
{
ImageView mImage = (ImageView) ((Activity) mActivityContext).findViewById(fn);
...
}
but it doesn't work!
mImage contains null image...
I can't find how can image contain outside of the activity.
Can you help me about how to implement drawing an ImageView outside of the activity?
Assuming mField is a member variable,
public class ImageRenderer implements Renderer {
Field mField = null;
use that in InitializeObject. Your Context is null because it wasn't set when you called it statically.
private boolean InitializeObject(int width, int height)
{
...
mField.SetField(width, height, R.drawable.image);
...
return true;
}
After you have set
mField = new Field(mActivityContext);
Try this (emptyimage is the image i have in my drawable)
mImage.setImageResource(R.drawable.emptyimage);