I want to zoom text that is displayed at center of screen as per user choice. How can I achieve this ?
Using pinch multitouch cannot be tested on emulator and I want something that I can test on Android emulator.
Can I use zoom in and out controls to control only text view for my layout ?
Or Can I use webview to contain a text as webview has default zoom in out buttons ?
Can I use zoom in and out controls to
control only text view for my layout ?
There is no built-in support for that. You can probably achieve this effect yourself by drawing the text using the 2D graphics APIs (Canvas) and touch events. Or, intercept touch events on a TextView and change the font size of the text.
This is my answer for that
public class Songs extends SherlockActivity implements OnTouchListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_songs);
context = this;
sett = new SettRenderingEngine(context);
Intent i = getIntent();
song = i.getStringExtra("song");
singer = i.getStringExtra("singer");
lyrics = i.getStringExtra("lyrics");
txt_song_title = (TextViewPlus) findViewById(R.id.song_title);
txt_singer = (TextViewPlus) findViewById(R.id.singer);
txt_song_lyrics = (TextViewPlus) findViewById(R.id.song_lyrics);
txt_song_title.setText(sett.getSettString(song));
txt_singer.setText(sett.getSettString(singer));
txt_song_lyrics.setText(sett.getSettString(lyrics));
txt_song_lyrics.setOnTouchListener(this);
scaleGestureDetector = new ScaleGestureDetector(this,
new simpleOnScaleGestureListener());
}
public class simpleOnScaleGestureListener extends
SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
float size = txt_song_lyrics.getTextSize();
float factor = detector.getScaleFactor();
float product = size * factor;
txt_song_lyrics.setTextSize(TypedValue.COMPLEX_UNIT_PX, product);
size = txt_song_lyrics.getTextSize();
return true;
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
scaleGestureDetector.onTouchEvent(event);
return true;
}
}
For Zoom In Zoom Out
public class ZoomControls extends AppCompatActivity
{
Button zoomin, zoomout;
TextView text;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoomcontrols);
zoomin = (Button) findViewById(R.id.zoomin);
zoomout = (Button) findViewById(R.id.zoomout);
text = (TextView) findViewById(R.id.text);
zoomin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
float x = text.getScaleX();
float y = text.getScaleY();
text.setScaleX((float) (x + 1));
text.setScaleY((float) (y + 1));
}
});
zoomout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
float x1 = text.getScaleX();
float y1 = text.getScaleY();
text.setScaleX((float) (x1 - 1));
text.setScaleY((float) (y1 - 1));
}
});
}
}
Related
I have been working on making Sudoku grid whose cell's value changes whenever I touch on a cell. So I have implemented this sudoku grid in a LinearLayout by Child View, and tried using OnTouch method, but it is not working. I tried using log method to check whether onTouch is actually called, but it seemes that this method is perfectly ignored. I have been searching for solutions on other question, but it seems none of those solutions helped. I feel kinda suck here, and any help would be greatly appreciated.
Here is my code:
SudokuActivity.java
package snacker.nonogramsolver;
import ...; /*many things are imported here*/
public class SudokuActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sudoku);
Button btn = (Button)findViewById(R.id.btn_clear);
Sudoku sdk = new Sudoku(this);
sdk.setOnTouchListener(sdk);
}
}
;
Sudoku.java
package snacker.nonogramsolver;
import ...;
public class Sudoku extends View implements View.OnTouchListener {
int mWidth = 9;
int mHeight = 9;
int mCellWidth, mCellHeight;
int mCellMargin;
int mEdgeThick;
int mStatus;
int mTextSize;
int mXNow = -1, mYNow = -1;
int[][] mBoard = new int[9][9];
Point mBoardPt;
Paint mTextPaint, mTileEdgePaint;
final static int VALID = 0;
public Sudoku(Context context){
super(context);
initializeBoard();
}
public Sudoku(Context context, AttributeSet attrs){
super(context, attrs);
initializeBoard();
}
#Override
protected void onDraw(Canvas canvas){
/* There are some codes here */
Log.d("LogTest","OnDraw Complete");
}
public void initializeBoard(){
for (int x=0; x< mWidth; x++){
for (int y=0; y< mHeight; y++){
mBoard[x][y] = 0;
}
}
invalidate();
}
public boolean onTouch(View v, MotionEvent event){
Log.d("LogTest","Touched?"); /* LOG NOT ACTIVE HERE */
if(event.getAction() == MotionEvent.ACTION_DOWN){
mXNow = getBoardX(event.getX());
Log.d("LogTest","" + mXNow); /* LOG NOT ACTIVE HERE */
mYNow = getBoardY(event.getY());
Log.d("LogTest","" + mYNow); /* LOG NOT ACTIVE HERE */
mBoard[mXNow][mYNow] = mBoard[mXNow][mYNow] + 1;
invalidate();
return true;
}
else return false;
}
int getBoardX(float scrx){
int x = (int)((scrx) / mCellWidth);
if (x < 0) x = 0;
if (x > 8) x= 8;
return x;
}
int getBoardY(float scry){
int y = (int)((scry) / mCellHeight);
if (y < 0) y = 0;
if (y > 8) y = 8;
return y;
}
}
Edit: added activity XML file.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="#+id/activity_sudoku"
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="snacker.nonogramsolver.SudokuActivity">
<snacker.nonogramsolver.Sudoku
android:id="#+id/SudokuGrid"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/btn_clear"
android:layout_width="150dp"
android:layout_height="30dp"
android:layout_weight="0.06"
android:text="Clear" />
</LinearLayout>
You cannot directly add touchListener by just creating object of
Sudoku class. You should add view in xml or programatically.
Your Activity
public class MyActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//initializing custom views
MyCustomView1 myCustomView1 = new MyCustomView1(parameterList);
MyCustomView2 myCustomView2 = new MyCustomView2(parameterList);
//adding both custom views to the main activity
mainView.addView(myCustomView1);
mainView.addView(myCustomView1);
//adding custom listener to the custom view 1
myCustomView1.setCustomEventListener(new OnCustomEventListener() {
#Override
public void onEvent() {
//firing an event of custom view 1
Toast.makeText(MainActivity.this, "Touched custom view 1",
Toast.LENGTH_SHORT).show();
}
});
//adding custom listener to the custom view 2
myCustomView2.setCustomEventListener(new OnCustomEventListener() {
#Override
public void onEvent() {
//firing an event of custom view 2
Toast.makeText(MainActivity.this, "Touched custom view 2",
Toast.LENGTH_SHORT).show();
}
});
}
}
Your CustomView 1
public class MyCustomView1 extends LinearLayout{
OnCustomEventListener myCustomEventListener;
public MyCustomView1(ParameterList){
super(ContextFromParameterList);
//Just adding something to the custom view 1 in order to distinguish it on the screen
TextView tv = new TextView(ContextFromParameterList);
tv.setText("Hello world from custom view 1");
addView(tv);
this.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
//delegating one event to another (delegating touch event to custom event)
if (MyCustomView1.this.myCustomEventListener != null)
MyCustomView1.this.myCustomEventListener.onEvent();
return false;
}
}); }
public void setCustomEventListener(OnCustomEventListener
eventListener) {
//setting custom listener from activity
myCustomEventListener = eventListener; } }
Your CustomView2
public class MyCustomView2 extends LinearLayout {
OnCustomEventListener myCustomEventListener;
public MyCustomView2(ParameterList) {
super(ContextFromParameterList);
//Just adding something to the custom view 1 in order to distinguish it on the screen
TextView tv = new TextView(ContextFromParameterList);
tv.setText("Hello world from custom view 2");
addView(tv);
this.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
//delegating one event to another (delegating touch event to custom event)
if (MyCustomView2.this.myCustomEventListener != null)
MyCustomView2.this.myCustomEventListener.onEvent();
return false;
}
});
}
public void setCustomEventListener(OnCustomEventListener eventListener) {
//setting custom listener from activity
myCustomEventListener = eventListener;
}
}
Your listener interface:
public interface OnCustomEventListener{
//interface defines one method. Can be more and methods may have parameters
public void onEvent();
}
Here is the problem I am facing. On a empty relative layout, when touched textview is instantiated at the touched x y position. I got this far correct, but the problem is that when I touch on the empty space near already instantiated view, previous view and currently placed views are overlapped. I tried by the getting the child views of the layout and checking the current view and already placed view using rect data that if they intersect. How to solve this problem?
Here is the code:
public class MainActivity extends AppCompatActivity
{
private int id = 0;
private RelativeLayout root;
private RelativeLayout.LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_designer);
root = (RelativeLayout) findViewById(R.id.rootlayout);
root.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
instantiateView(v, event);
break;
}
return true;
}
});
}
private void instantiateView(View v, MotionEvent event)
{
int x = (int) event.getX();
int y = (int) event.getY();
TextView bt = new TextView(DesignerActivity.this);
bt.setText("1");
bt.setId(++id);
bt.setBackgroundColor(Color.BLACK);
bt.setTextColor(Color.WHITE);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
showDialog();
}
});
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(x, y, 0, 0);
bt.setLayoutParams(params);
//((ViewGroup) v).addView(bt);
if(root.getChildCount() <= 0)
{
((ViewGroup) v).addView(bt);
}
else
{
for (int i = 0; i < root.getChildCount(); i++)
{
if (!checkCollision(bt, root.getChildAt(i)))
{
if(bt != root.getChildAt(i))
{
((ViewGroup) v).addView(bt);
}
}
}
}
}
private void showDialog()
{
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_layout);
Button editBtn = (Button) dialog.findViewById(R.id.button1);
Button deleteBtn = (Button) dialog.findViewById(R.id.button2);
editBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
dialog.dismiss();
}
});
deleteBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
dialog.dismiss();
}
});
dialog.show();
}
private boolean checkCollision(View v1, View v2)
{
Rect r1 = new Rect(v1.getLeft(), v1.getTop(), v1.getRight(), v1.getBottom());
Rect r2 = new Rect(v2.getLeft(), v2.getTop(), v2.getRight(), v2.getBottom());
return r1.intersect(r2);
}
}
You are using Relative Layout that's why your Textviews are overlapping.
If you don't want the overlapping and want to place it next or somewhere else to the overlapped view , it is your decision. Just check if they intersect and take appropriate decision based on your requirement.
Below line is the problem in your code.
Rect r1 = new Rect(v1.getLeft(), v1.getTop(), v1.getRight(), v1.getBottom());
You set the params' Margin does not mean that you will get desired left,top,right, bottom values.You will get these values right after the inflation of your view hierarchy.
You can use this function:
private boolean checkCollision(View v1, View v2)
{
int leftMargin = ((RelativeLayout.LayoutParams) v1.getLayoutParams()).leftMargin;
int topMargin = ((RelativeLayout.LayoutParams) v1.getLayoutParams()).topMargin;
Rect r1 = new Rect(root.getPaddingLeft() + leftMargin, root.getPaddingTop() + topMargin,
root.getPaddingLeft() + leftMargin + v2.getWidth(), root.getPaddingTop() + topMargin + v2.getHeight());
Rect r2 = new Rect(v2.getLeft(), v2.getTop(), v2.getRight(), v2.getBottom());
return r1.intersect(r2);
}
After that use
params.addRule(); according to your requirement where you want to place your overlapping view.
I'm having troubles with the method onTouch(). The code I'm using to implement it is the following.
public class EjemploView extends View implements OnTouchListener {
...
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getActionMasked()==0) {
slider2.setCenX(slider2.getCenX() - 1);
}
return false;
}
}
The point is that I set a debugger stop inside onTouch method and even if I touch the screen it will never go inside it. What am I doing wrong?
Adding as an answer, simply so that it makes more sense.
You are implementing onTouchListener but you dont set it as your onTouchListener. Thus you are left with a fully functioning onTouchListener in your view that does not ever get called.
public EjemploView(Context context) {
super(context);
/** \/ Add this line right here \/ */
setOnTouchListener(this);
Resources res = context.getResources();
drawableFader = res.getDrawable(R.drawable.fader);
drawableSlider=res.getDrawable(R.drawable.slider);
fader1 = new Grafico(this, drawableFader);
fader2 = new Grafico(this, drawableFader);
slider1 = new Grafico(this, drawableSlider);
slider2 = new Grafico(this, drawableSlider);
fader1.setAlto(350);
fader1.setAncho(64);
fader2.setAlto(350);
fader2.setAncho(64);
fader2.setAngulo(90);
slider1.setAlto(90);
slider1.setAncho(55);
slider2.setAlto(90);
slider2.setAncho(55);
slider2.setAngulo(90);
}
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
setContentView(new EjemploView(this));
That's the place where I instantiate the view
public class EjemploView extends View implements OnTouchListener {
private Drawable drawableFader, drawableSlider;
private Grafico fader1, fader2, slider1, slider2;
public EjemploView(Context context) {
super(context);
Resources res = context.getResources();
drawableFader = res.getDrawable(R.drawable.fader);
drawableSlider=res.getDrawable(R.drawable.slider);
fader1 = new Grafico(this, drawableFader);
fader2 = new Grafico(this, drawableFader);
slider1 = new Grafico(this, drawableSlider);
slider2 = new Grafico(this, drawableSlider);
fader1.setAlto(350);
fader1.setAncho(64);
fader2.setAlto(350);
fader2.setAncho(64);
fader2.setAngulo(90);
slider1.setAlto(90);
slider1.setAncho(55);
slider2.setAlto(90);
slider2.setAncho(55);
slider2.setAngulo(90);
}
#Override
protected void onSizeChanged(int ancho, int alto, int ancho_anter, int alto_anter) {
super.onSizeChanged(ancho, alto, ancho_anter, alto_anter);
// Una vez que conocemos nuestro ancho y alto.
fader1.setCenX(ancho / 4 - 31);
fader1.setCenY(alto / 4 - 50);
slider1.setCenX(ancho / 4 - 28);
slider1.setCenY(alto / 4 - 50);
fader2.setCenX(ancho - 271);
fader2.setCenY(alto / 4 - 50);
slider2.setCenX(ancho - 277);
slider2.setCenY(alto / 4 - 50);
}
#Override
synchronized protected void onDraw(Canvas canvas) {
fader1.dibujaGrafico(canvas);
fader2.dibujaGrafico(canvas);
slider1.dibujaGrafico(canvas);
slider2.dibujaGrafico(canvas);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "I've reached this point");
if(event.getActionMasked()==0) {
slider2.setCenX(slider2.getCenX() - 2);
}
return false;
}
}
And that's my whole code for the view. It is displaying it because I can see the drawables.
You are implementing a new interface, but you should use the already defined onTouchEvent(MotionEvent event). Just override it.
class CustomImageView extends ImageView {
...
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked();
Log.d(TAG, String.valueOf(action));
return false;
}
}
i found this code in a post that used on touch listener for linear layout.
in linear layout there is some child layout and each one play same sound but with pitch . now how can i use each child to play a different sound .
the other word how can i access to each child?
public class MainActivity extends Activity {
LinearLayout pianoKeysContainer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
pianoKeysContainer = (LinearLayout) findViewById(R.id.key_container);
pianoKeysContainer.setOnTouchListener(onYourViewTouchListener);
}
//Here we load the view positions after render it and fill the array with the positions
private List<Integer> positionsLeft_whiteKeys = new ArrayList<Integer>();
private List<Integer> positionsRight_whiteKeys = new ArrayList<Integer>();
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
for (int i = 0; i < pianoKeysContainer.getChildCount(); i++)
{
//positionsLeft_whiteKeys holds the start x of each view.
positionsLeft_whiteKeys.add(pianoKeysContainer.getChildAt(i).getLeft());
//positionsRight_whiteKeys holds the end x of each view.
positionsRight_whiteKeys.add(pianoKeysContainer.getChildAt(i).getRight());
}
}
public View.OnTouchListener onYourViewTouchListener = new View.OnTouchListener()
{
float positionX;
FrameLayout pianoKey;
FrameLayout lastPlayedKey;
ArrayList<FrameLayout> pressedKeys = new ArrayList<FrameLayout>();
#Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
positionX = motionEvent.getX();
float pitch;
//Looping on the child of the layout which contains the piano keys
for (int x = 0; x < ((LinearLayout) view).getChildCount(); x++)
{
// Calculating the pitch to get good chords
pitch = (float) Math.pow(Math.pow(2.0, 1 / 12.0), (float) x);
pianoKey = (FrameLayout) ((LinearLayout) view).getChildAt(x);
if (positionsLeft_whiteKeys.size() >= 0 && positionsRight_whiteKeys.size() >= 0)
{
if (positionX > positionsLeft_whiteKeys.get(x) && positionX < positionsRight_whiteKeys.get(x))
{
pianoKey = (FrameLayout) ((LinearLayout) view).getChildAt(x);
if (pianoKey != null)
{
pianoKey.setBackgroundResource(R.drawable.dinger14);
pressedKeys.add(pianoKey);
}
if (lastPlayedKey != pianoKey)
playKey(pitch);
lastPlayedKey = pianoKey;
break;
}
if (lastPlayedKey != null)
{
pianoKey.setBackgroundResource(R.drawable.dinger14);
lastPlayedKey.setBackgroundResource(R.drawable.dinger14);
}
}
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP)
{
lastPlayedKey = null;
for (FrameLayout pressedKey : pressedKeys)
{
pressedKey.setBackgroundResource(R.drawable.dinger14);
}
}
return false;
}
};
//This is sound play method
SoundPool sp = new SoundPool(1, AudioManager.STREAM_MUSIC, 1);
public void playKey(final float pitch)
{
//here you should store your piano sound at res/raw then load it
sp.load(this, R.raw.chitare3, 1);
sp.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener()
{
#Override
public void onLoadComplete(SoundPool soundPool, int i, int i2)
{
soundPool.play(i, 0.99f, 0.99f, 1, 0, pitch);
}
});
}
}
If you have no need of parent on touch event then directly apply this same event on each child...
pianoKeysContainer1 = (LinearLayout) findViewById(R.id.key_child1);
pianoKeysContainer2 = (LinearLayout) findViewById(R.id.key_child2);
pianoKeysContainer1.setOnTouchListener(onYourViewTouchListener);
pianoKeysContainer2.setOnTouchListener(onYourViewTouchListener);
You can apply onYourViewTouchListener onTouchListener on each child as shown above.
Then in View.onTouchListener check which child listener is called by checking view id.
public View.OnTouchListener onYourViewTouchListener = new View.OnTouchListener()
{
float positionX;
FrameLayout pianoKey;
FrameLayout lastPlayedKey;
ArrayList<FrameLayout> pressedKeys = new ArrayList<FrameLayout>();
#Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
// Check **view id** here and apply required action based on this view id.
.............
.............
public class UnitConverterActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
LinearLayout mLinearLayout;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLinearLayout = new LinearLayout(this);
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.mainmenu);
//i.setAdjustViewBounds(false);
i.setScaleType(ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mLinearLayout.addView(i);
setContentView(mLinearLayout);
//setContentView(R.layout.main);
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}
I have used the above method to load an image for the main menu I am trying to create. The image has four areas and each will be used to call a particular function of the app. Now I am trying to implement touch interface on those areas. I know how to define the range of pixels for that purpose but I am at loss on how to implement OnTouchListner on the image. Please help me in this regard.
If your image was split into four rectangular quarters (say)
then in onCreate have:
i.setOnTouchListener(this);
and for your listener, something like this (illustrates the principle only):
#Override
public boolean onTouch(View v, MotionEvent mev) {
int width = v.getWidth();
int height = v.getHeight();
float x = mev.getX();
float y = mev.getY();
String msg;
if (x < width / 2) {
if (y < height / 2)
msg = "Top left quarter";
else
msg = "Bottom left quarter";
} else {
if (y < height / 2)
msg = "Top right quarter";
else
msg = "Bottom right quarter";
}
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
return false;
}
Just put this code in onCreate().
i.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//your code
}
}