Translate & Rotate (平移和旋转组合变换)
按照正常的理解,先平移和先旋转没什么区别吧,但是经测试,的确是有很大的区别的。甚至是结果完全的不同。示例如下:
先画一个方块绕着中心点自转。
// SQUARE A // Save the current matrix. gl.glPushMatrix(); // Rotate square A counter-clockwise. gl.glRotatef(angle, 0, 0, 1); // Draw square A. square.draw(gl); // Restore the last matrix. gl.glPopMatrix();// 恢复了变换矩阵
然后再画一个方块B绕着方块A做旋转,正常代码(先旋转再平移)应该如下:
// SQUARE B // Save the current matrix gl.glPushMatrix(); // Rotate square B before moving it, making it rotate around A. gl.glRotatef(-angle, 0, 0, 1); // Move square B. gl.glTranslatef(2, 0, 0); // Scale it to 50% of square A gl.glScalef(.5f, .5f, .5f); // Draw square B. square.draw(gl); gl.glPopMatrix();
但是如果先平移再旋转:
gl.glTranslatef(2, 0, 0);// 先平移 gl.glRotatef(-angle, 0, 0, 1);//再旋转
就造成方块A和方块B同轴旋转了。
再有旋转
public abstract void glRotatef (float angle, float x, float y, float z)
中参数X,Y,Z是一个整体,应该是(x,y,z)的向量坐标。
原理性的问题进一步了解中。
错误:findViewById返回Null,报nullpointer错误
网上搜了下,总结原因,一般为一下几种:
1.在另一个view的元素应该用baseView.findViewById()来拿
findViewById()是要指定view的,如果在该view下找不到,自然报null。平时注意养成写view.findViewById()的习惯就不容易错了。
2.findViewById在setContentView(R.layout.main);之前.
即在setContentView调用之前,调用了findViewById去找main布局中的界面元素lv_contactbook,那么所得到的lv一定是null。正确的做法是将上面代码中加粗的哪一行,挪至setContentView方法调用之后即可。
3. 使用了id的旧风格
通过findViewById()获取一个Button时一直返回null值,百思不得其解。最后发现是因为在layout文件中使用了id的旧风格,如下所示:
<Button id="@+id/btn_ok" />
改成android:id就成功了。
<Button android:id="@+id/btn_ok" />
4. 没有重写BottomTab方法 (这个情况还没遇到,网上有人提到这种情况,欢迎验证一下)
自定义View 的时候 必须重写以下方法
public BottomTab(Context context, AttributeSet attrs) { super(context, attrs);
}
5.clean一下工程,让ID重新生成
这种情况是调用LayoutInflater.inflate将布局xml规定的内容转化为相应的对象。比如有rowview.xml布局文件(比如在自定义Adapter的时候,用作ListView中的一行的内容的布局),假定在自定的Adapter的getView方法中有类似如下的代码:
View rowview = (View)inflater.inflate(R.layout.rowview, parent, false);
TextView tv_contact_id =(TextView)rowview.findViewById(R.id.tv_contact_id);
TextView tv_contactname =(TextView)rowview.findViewById(R.id.tv_contactname);
有时候居然也会发现rowview非空,但tv_contact_id和tv_contactname都是null!仔细看代码,怎么也看不出错误来。到底是什么原因造成的呢?答案是Eclipse造成的,要解决这个问题,需要这个项目clean一次(Project菜单 -> Clean子菜单),这样就OK了。
最近做了个小demo,需要在demo中访问其他apk中的信息。 网上版本很多,有用的很少。经过反复查阅和试验,总结了几种方法。
(1)demo很简单,页面上只有一个按钮,点击按钮可以访问其他apk中相应的activity。Demo的主要代码
如下:
package com.example.demo; import com.example.demo.R; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { method1(); } }); return true; } /* * 1.利用compnent方式访问其他apk的(主activity),无需设置androidmanifest.xml */ public void method1() { // 这些代码是启动另外的一个应用程序的主Activity ComponentName componetName = new ComponentName( // 这个是另外一个应用程序的包名 ,androidmanifest.xml中的package值!!! "com.amaker.test", // 这个参数是要启动的Activity (主activity) "com.amaker.test.MainActivity"); try { Intent intent = new Intent(); intent.setComponent(componetName); startActivity(intent); } catch (Exception e) { Toast.makeText(getApplicationContext(),"没有找到应用程序!!!", 0).show(); } } /* * 2.利用compnent方式访问其他apk的(非主activity),需要设置androidmanifest。xml中非主activity的exported属性,具体如下: * 被访问的activity是"com.amaker.ch03.drawable.TestBitmapActivity" 则需要设置的是:<activity android:name="com.amaker.ch03.drawable.TestBitmapActivity" android:exported="true"/> */ public void method2() { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.amaker.test","com.amaker.ch03.drawable.TestBitmapActivity")); //"com.amaker.ch03.string.TestStringActivity")); //intent.setAction("android.intent.action.VIEW"); startActivity(intent); } /* * 3.设置androidmanifest.xml访问其他apk的(非主activity) * 注意:使用这种方式的时候需要在被调用的apk的androidmanifest.xml里做如下设置(访问非主activity) <activity * android:name="com.amaker.ch03.xml.TestXmlActivity"> <intent-filter> * <action android:name="android.intent.action.xml" /> <data * android:scheme="info" /> <category * android:name="android.intent.category.DEFAULT" /> </intent-filter> * </activity> */ public void method3() { Intent intent = new Intent("android.intent.action.xml", Uri.parse("info://调用其他应用程序的Activity")); startActivity(intent); } }
(2)被调用的工程的名字是:Chapter03_Resource.
这个android小工程,之所以可以被Demo调用,是因为AndroidManifest.xml被做了修改。具体代码如
下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.amaker.test" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.amaker.ch03.color.TestColorActivity"> <action android:name="android.intent.action.color" /> <category android:name="android.intent.category.DEFAULT" /> </activity> <activity android:name="com.amaker.ch03.string.TestStringActivity" android:exported="true"/> <activity android:name="com.amaker.ch03.dimen.TestDimensionActivity"/> <activity android:name="com.amaker.ch03.xml.TestXmlActivity"> <intent-filter> <action android:name="android.intent.action.xml" /> <data android:scheme="info" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:name="com.amaker.ch03.drawable.TestBitmapActivity" android:exported="true"/> <activity android:name="com.amaker.ch03.layout.TestLayoutActivity"/> <activity android:name="com.amaker.ch03.menu.TestMenuActivity"/> </application> <uses-sdk android:minSdkVersion="3" /> </manifest>
参照Demo中的注释即可理解。